Saturday, December 18, 2010

A new world for integration: SAML and Identity

SAML was initially a standard for cross-domain SSO. A user who is logged on to the domain *.i8c.be could transparently point his browser to a web application in another domain *.cronos.be without having to authenticate again. His identity (and other attributes) are passed on transparently, behind the scenes. Many mechanisms were defined to exchange the information contained in SAML token (signed XML structures) between an Identity Provider and a Relying Party, including SOAP very early on (the SAML SOAP Binding).

But SAML was taken further. WS-Security SAML Token Profile allows the use of SAML tokens in SOAP messages secured with WS-Security. And WS-Trust and its Secure Token Service standardized the mechanism to obtain or exchange SAML (or other) tokens.
The STS is a standard (web) service to obtain such a SAML token: 1) through standard authentication mechanisms or 2) by exchanging one token for another (SAML to SAML, non-SAML to SAML or SAML to non-SAML).

But transferring SAML tokens between domains means the exchange of information between heterogeneous organizations. The SAML standard does not define how attributes within the SAML tokens should be named nor what their content should exactly look like. Every organziation is free to specify how information is structured in a SAML token:
  • what information or attributes is contained in the SAML token: name, cost center, department, ...
  • how the atrributes should are named, e.g. LastName or lname?
  • how the information in the attributes is represented
Imagine a vendors of office materials (Staples) that wants to offer a SSO experience to the employees of its majore customers. If every customer (large enterprises themselves) use a different SAML token structure, the office material vendor will have a great time translating the information from these different SAML tokens to its own attributes. And what if information is missing in the SAML token, e.g. what is the maximum value that employee may purchase?

Another integration challenge!

Note: Microsoft prefers the use of the term claim

Authored by: Guy

Friday, December 10, 2010

Command Line JMX + SSL

The tool I use for command line JMX and which I think really works well is http://wiki.cyclopsgroup.org/jmxterm

You can download and start the single jar as shown below. In this example I'm connecting to a HornetQ instance.
[jeroen@homesrv~]# java -jar jmxterm-1.0-alpha-4-uber.jar -l service:jmx:rmi:///jndi/rmi://192.168.1.3:10995/jmxrmi
Welcome to JMX terminal. Type "help" for available commands.
$>
Next you can fetch a list of all the available beans (not showing all the beans):
$>beans #domain = JMImplementation: JMImplementation:type=MBeanServerDelegate #domain = com.sun.management: com.sun.management:type=HotSpotDiagnostic #domain = java.lang: java.lang:name=Code Cache,type=MemoryPool ... #domain = java.util.logging: java.util.logging:type=Logging #domain = org.hornetq: org.hornetq:address="hornetq.notifications",module=Core,name="notif.fb6d27d5-02ac-11e0-ae9b-1cc1de6fb76e",type=Queue ... org.hornetq:module=JMS,name="TEST.IN",type=Queue org.hornetq:module=JMS,type=Server
To see the available attributes and operations on a specific MBean you can use the info command:
$>info -b org.hornetq:module=JMS,name="TEST.IN",type=Queue #mbean = org.hornetq:module=JMS,name="TEST.IN",type=Queue #class name = org.hornetq.jms.management.impl.JMSQueueControlImpl # attributes %0 - Address (java.lang.String, r) %1 - ConsumerCount (int, r) %2 - DeadLetterAddress (java.lang.String, rw) %3 - DeliveringCount (int, r) %4 - ExpiryAddress (java.lang.String, rw) %5 - JNDIBindings ([Ljava.lang.String;, r) %6 - MessageCount (int, r) ... %12 - Temporary (boolean, r) # operations %0 - void addJNDI(java.lang.String jndiBinding) %1 - boolean changeMessagePriority(java.lang.String messageID,int newPriority) %2 - int changeMessagesPriority(java.lang.String filter,int newPriority) %3 - int countMessages(java.lang.String filter) ... %20 - int sendMessagesToDeadLetterAddress(java.lang.String filter) #there's no notifications
To get the actual value of an MBean attribute, use the get command
$>get -b org.hornetq:module=JMS,name="TEST.IN",type=Queue MessageCount
#mbean = org.hornetq:module=JMS,name="TEST.IN",type=Queue:
MessageCount = 0;
To invoke an operation use the run command:
$>run -b org.hornetq:module=JMS,name="TEST.IN",type=Queue resetMessageCounter
#calling operation resetMessageCounter of mbean org.hornetq:module=JMS,name="TEST.IN",type=Queue
#operation returns:
null

$>get -b org.hornetq:module=JMS,name="TEST.IN",type=Queue MessageCount
#mbean = org.hornetq:module=JMS,name="TEST.IN",type=Queue:
MessageCount = 0;
As you can see the tool is very easy to use. BUT, since we are talking about Java Management Extensions which let you control, in this case, a HornetQ server, I think some security is in order.
The JMX agent on the JVM is by default started with TLS/SSL and username + password authentication. More information on how to set this up is on: http://download.oracle.com/javase/1.5.0/docs/guide/management/agent.html#auth. In the example above, security was switched off, which is easy to do by setting the following properties:
com.sun.management.jmxremote.authenticate=false
com.sun.management.jmxremote.ssl=false

Now to enable TLS/SSL and username + password on the JMX agent set the following properties, first 2 were set before as well:
com.sun.management.jmxremote com.sun.management.jmxremote.port=10999 com.sun.management.jmxremote.password.file=$HOME/jmxremote.password javax.net.ssl.keyStore=hornetq-srv1-keystore.jks javax.net.ssl.keyStorePassword=changeit
The jmxremote.password is following the template under java.home/jre/lib/management/jmxremote.password.template

On the client side, in this case jmxterm, you need to set the following properties:

javax.net.ssl.trustStore=jmxclient-truststore.jks
javax.net.ssl.trustStorePassword=changeit
This is all following the java specs and should work, but when we start with the following command
[jeroen@homesrv~]# java -Djavax.net.ssl.trustStore=jmxclient-truststore.jks -Djavax.net.ssl.trustStorePassword=changeit -jar jmxterm-1.0-alpha-4-uber.jar -l service:jmx:rmi:///jndi/rmi://192.168.1.3:10999/jmxrmi
The following error pops up:
constituent[0]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/jmxterm.jar
constituent[1]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-beanutils.jar
constituent[2]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-cli.jar
constituent[3]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-collections.jar
constituent[4]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-lang.jar
constituent[5]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-logging.jar
constituent[6]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-io.jar
constituent[7]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/jcli.jar
constituent[8]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/jline.jar
---------------------------------------------------
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
javax.net.ssl.SSLKeyException: RSA premaster secret error
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:286)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:110)
at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2327)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:279)
at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:248)
at org.cyclopsgroup.jmxterm.cc.SessionImpl.doConnect(SessionImpl.java:85)
at org.cyclopsgroup.jmxterm.cc.SessionImpl.connect(SessionImpl.java:49)
at org.cyclopsgroup.jmxterm.cc.CommandCenter.connect(CommandCenter.java:110)
at org.cyclopsgroup.jmxterm.boot.CliMain.execute(CliMain.java:139)
at org.cyclopsgroup.jmxterm.boot.CliMain.main(CliMain.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.Launcher.launchStandard(Launcher.java:353)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:264)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.uberjar.boot.Bootstrapper.bootstrap(Bootstrapper.java:209)
at org.codehaus.classworlds.uberjar.boot.Bootstrapper.main(Bootstrapper.java:116)
Caused by: javax.net.ssl.SSLKeyException: RSA premaster secret error
at com.sun.net.ssl.internal.ssl.RSAClientKeyExchange.(RSAClientKeyExchange.java:97)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:673)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:230)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at java.io.DataOutputStream.flush(DataOutputStream.java:106)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:211)
... 25 more
Caused by: java.security.NoSuchAlgorithmException: SunTlsRsaPremasterSecret KeyGenerator not available
at javax.crypto.KeyGenerator.(DashoA13*..)
at javax.crypto.KeyGenerator.getInstance(DashoA13*..)
at com.sun.net.ssl.internal.ssl.JsseJce.getKeyGenerator(JsseJce.java:223)
at com.sun.net.ssl.internal.ssl.RSAClientKeyExchange.(RSAClientKeyExchange.java:89)
... 37 more
It looks like the uberjar is doing something fishy with the classloaders which make that the standard sun security provider is no longer available. Bummer ...

This is the only explanation I can think of. Because when connecting with jconsole, like below, I only need to enter the username/pwd. No other issues.
[jeroen@homesrv~]# jconsole -J-Djavax.net.ssl.trustStore=jmxclient-truststore.jks -J-Djavax.net.ssl.trustStorePassword=changeit service:jmx:rmi:///jndi/rmi://192.168.1.3:10995/jmxrmi
I guess for command line jmx with SSL I'll have to look elsewhere ...
If someone has ideas please post :-)


Authored by: Jeroen

Friday, December 3, 2010

Scary: backdoor in FTP server software

While reading security.nl, I picked up the news that hackers had put a backdoor in the popular FTP server ProFTPD. A version of the software containing a backdoor was put on the distribution server by some hackers.

How often does one install software from the Internet without any verification. Yes, there are the fingerprints, but who checks them? Even more scary if you were the one installing that software on a customers's server.

And if some hacker ever finds its way into the Windows Update software distribution mechanism, the world will come to a halt (don't smile you Apple users).

Authored by: Guy

Monday, November 15, 2010

Java on Microsoft Azure

Triggered by my colleague Koen Van Oost and the upcoming Microsoft session at Devoxx, I looked into Java on the Microsoft Azure platform. Watched the talk "Open in the cloud: Windows Azure and Java" of PDC10. I wasn't aware that one could run Tomcat on Azure! Well, seems to be the case already since 2009. But the Eclipse tooling and JDBC connection to the SQL Azure Database are brand new. During the talk, it was also shown how the Fujitsu Interstage application server can run on Azure. Having WebLogic or WebSphere Application Server running on Azure would be very big news! For now, let's see how the ESB and integration capabilities of Azure are usable from Java.

Authored by: Guy

Friday, November 12, 2010

Devoxx 2010

Next week is Devoxx! Three talks and three speakers that I can really recommend:
In particular as I invited the speakers myself for these talks! Just too bad that I can't be there myself, damned.

But many more interesting things: Activiti in Action by Tom Baeyens, Scalable Java Applications on Azure by Microsoft, Comparing JVM Web Frameworks by Matt Raible, Encryption Bootcamp on the JVM, loads of NoSQL stuff, and so many more great talks.

Looking forward to meet you next week @ Devoxx on Monday, Tuesday or Wednesday.

Authored by: Guy

Thursday, November 11, 2010

Dell acquires Boomi

Boomi is a very interesting Integration-As-A-Service player. Integration in the cloud is a new trend that looks very promising. But what is not yet clear is the reason why Dell acquired Boomi. A big cloud player such as Google or Amazon or a big software players such as Microsoft, IBM or SAP have probably more chances. Curious to see what direction Dell will take with Boomi.

Authored by: Guy

XML schema's for verticals

With XML as the alphabet, many languages are defined through XML schema's. But typical is the way each vertical defines its own language. Latest example that I was pointed at: XML schema's for the oil industry at energistics.org.



But there are very little initiatives to define a common foundation, to define the words (nouncs, verbs) from which each vertical could define variations or specific XML languages. Many XML languages lead to many translations or transformations. Fine for us the integration experts, but overall not very efficient. ebXML Core Components gave the structure to define re-usable XML building blocks that could be used in different contexts and adapted based on region, industry, business process etc. But ebXML CC is used in some of the verticals, but not one a broad scale as is the case with good old EDIFACT.

And as the XML standards in the oil industry proof, the trend of the last 10 years continues, many domain specific XML languages, specific for each vertical.

Authored by: Guy

Monday, June 21, 2010

Cloud Computing Economies of Scale

Great recorded talk about the hardware and data centre side of cloud computing. This great presentation explains why it (also) makes sense to leverage cloud computing simply to have cost efficient hardware. Got pointed to it while listening to the Cloud Computing Show #31.

Also interesting (via the same podcast): CloudHarmony. The blog in particular contains different benchmark results (memory, IO, network) of a large number of Infrastructure-As-A-Service providers.

Authored by: Guy

Tuesday, June 15, 2010

B2B market

IBM keeps acquiring other companies:
  • Lombardi being a BPM solution of which some of my colleagues are quite enthusiatic.
  • Sterling is more an "old" player in the B2B space with products such as Gentran for B2B communication and ConnectDirect for managed file transfer. But Sterling is also an Integration Service Provider (Garnter) or still call it a Value Added Network? IBM sold its VAN to GXS quite a while ago.
  • Cast Iron Systems which is a new kid on the block, with a solution specificially targeting cloud integration. Also available as an appliance. And Cast Iron was rumoured to be developing a cloud based integration offering.
Funny to see and "old" (Sterling) and brand "new" player (Cast Iron) being acquired in the same timeframe. Of course I'm curious to see what IBM will do with these acquisitions. Will they die in a corner or be successor of the DataPower success story? And how will they explain and position all these technologies at customers?

Authored by: Guy

Sunday, April 18, 2010

Java: execute program without blocking

A long while ago that I had done some Java programming... How to run a program from within Java in a decent manner. While looking around for some sample code, most solutions use the Process.waitFor() method to wait for the process to terminate. But that will usually block forever as process writes data to stdout or stderr and nothing reads that output.

One option is to use a separate thread to read stdout/stderr. I opted for an even simpler approach: temporary files:

execCommand = execCommand + " > " + stdoutFile.getFileName();
execCommand = execCommand + " 2> " + stderrFile.getFileName();
// command/program > stdout-temp 2> sterr-temp
Process p = Runtime.getRuntime().exec(execCommand, null, currDir);

int exitValue = 0;
boolean isRunning = true;
int waitSeconds = 30;
while(isRunning && (waitSeconds > 0)) {
try {
exitValue = p.exitValue();
isRunning = false;
} catch(IllegalThreadStateException e) {
// process is still running, wait 1 second
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// ignore
}
}
waitSeconds--;
}
if (isRunning) {
p.destroy();
exitValue = 9999;
}

stdoutFile.delete();
stderrFile.delete();


Authored by: Guy

Saturday, April 17, 2010

Amazon pub/sub in the cloud

Amazon keeps extending its cloud offering. They have just added Amazon Simple Notification Service (SNS). SNS is a publish/subscribe mechanism.

Integration-As-A-Service
As explained in earlier posts, I expect Integration-As-A-Service to become more important. One of the larger players (Amazon, Google, EMC, Cisco, Microsoft, ...) may one day come up with a wonderful solution for Business-2-Business communication between organizations.

When I first learned about Simple Queuing Service of Amazon back in 2006, I intially thought that SQS could serve as a transport mechanism for B2B communication. But that didn't work out. As the message size of SQS was very limited, data first had to be stored on S3. Authentication and authorization were also very limited.

So I looked around in the SNS documentation to see what SNS actually is and see if it can serve as a basis for B2B communication. Amazon thinks SNS is usable for B2B or application integration:
Application integration: Amazon SNS can be used in workflow systems to relay events among distributed computer applications, move data between data stores, or update records in business systems. For example, in an order processing application, notification messages may be sent whenever a transaction occurs; a customer places an order, the transaction is forwarded to a payment processor for approval, and an order confirmation message is published to an Amazon SNS topic.

Some facts
  • Messages can be published over HTTP, HTTPS, E-mail or SQS
  • Proprietary solution/mechanism, not based on any standard (no AS1, AS2, SFTP, WS-Notification, WS-Eventing, ...)
  • Messages are (again) limited to 8KB. Just like SQS: too small.
  • Authentication is based on AWS accounts, so also every subscriber requires an AWS account, hindering factor.
  • Messages are pushed, not polled. This is good for performance. For polling, use SQS.
  • But when pushing, the subscriber must expose a web service or mail account. How to secure this: no authentication from Amazon to endpoint receiving notifications; no basic auth, no support for client certs, ...
  • Messages are signed by Amazon. This is good, very good. Signing is based on HmacSHA256.
Conclusion:
Nice and interesting, but not good enough... In particular the message size remains a blocking factor.

Questions left:
  • What happens if messages cannot be delivered for a longer periode of time? E.g. when a subscriber disappears?
  • How does a message that is published over HTTP exactly look like (signed, JSON)? What parameters are passed in the URL?
  • Can an SSL endpoint with self-signed cert receive notifications?
  • What if SSL cert of endpoint is expired?
  • Are mail messages signed and if yes, how?
  • How and when are messages actually persisted?
  • The publish service isn't idempotent it seems?
PS: all based on reading the docs, must confess that I didn't actually test it

Authored by: Guy

Wednesday, April 14, 2010

SSL Man-in-the-middle

Again a great "Security Now" podcast about SSL: how governments can sniff SSL traffic by enforcing Certificate Authorities to provide them with (intermediate CA) certificates. Based on this paper. Great story, recommended reading or listening!

Some things that I picked up:
  • Different CA's can provide you with SSL certificate for same URL (or whatever)
  • Internet Explorer (actually the Windows crypto) downloads extra CA's dynamically; so the list you see in IE can grow behind the scenes
  • Firefox manages the list of trusted CA's itself
  • There is no standard policy for when a CA is accepted by browser vendors
  • The list of trusted CA's should be based on your geographical location
  • Trusting a CA is somewhat equivalent to trusting a government
  • Browser should provide (advanced) users with extra features to help them decide if CA certificate should be trusted or not
In my daytime job, SSL/TLS is used a lot for communication between IT systems within the corporate firewall or with business partners across the Internet. Low level configuration of SSL/TLS is often not supported:
  • Configure single CA (or self-signed) cert to be trusted for specific outbound connection (e.g. when business partners have defined their "own CA")
  • Different SSL client certificate per outbound connection
  • Easy configuration revocation checks (OCSP etc); and checking if the revocation checks actually work
  • Different timeout settings per connection
  • Only accept SSL connections on specific interfaces
Authored by: Guy

    Thursday, March 11, 2010

    Claims explained


    SAML, WS-Security and the Secure Token Service of WS-Trust result in a very interesting mix, where federated identity and integration (web services) come together.
    Microsoft has published the free book(let) "A Guide to Claims–based Identity and Access Control". Obviously the book is focused on Microsoft technology, ADFS (code name Geneva), FAM and WIF in particular. But I found the first 2 chapters very informative and well written.

    E.g. interesting to have confirmation that applications need to keep maintaining fine grained (data level) authorizations themselves.

    Also intersting to read about the challenge of home realm discovery: how to know to what Identity provider an external user should be redirected to.

    One of the main challenges in my opionion with federated identity is the transformation of tokens/claims. Unless there is further standardization (profiles), the integration with each external business partners will require token transformations. There seems to be a general tendency in WS-land not to bother too much with the actual business content of SOAP messages or SAML tokens.

    The day when SAML tokens can be used in an interoperable manner to connect to back-end applications such as SAP or Oracle will be a great day. Looking forward to it.

    Authored by: Guy

    Sunday, February 28, 2010

    B2B market keeps moving

    As mentioned in the blog post of Gartner analyst Benoit Lheureux, the market of B2B products keeps moving, e.g. the acquisition of Foresight by Tibco.


    Interesting blog post as well on the SAP Developer Network: SAP will increase its stake in Crossgate and SAP sales people will (re-)sell the Crossgate B2B service offering.

    Note: I always confuse Crossgate and Northgate. NorthgateArinso is a SAP oriented provider of HR IT services and acquired the Belgian company Arinso.

    Authored by: Guy

    Monday, February 8, 2010

    SOAP over JMS not a standard

    I was really convinced it was a standard. Apparantly not. The best I can find is a W3C recommendation (http://www.w3.org/Submission/SOAPJMS/). It seems it never made it to be a standard. Also in the JMS spec (http://jcp.org/en/jsr/detail?id=914), there is only mention of HTTP as transport for a SOAP binding.
    A bit strange, WSIF has had this possibility for years (http://ws.apache.org/wsif/providers/wsdl_extensions/jms_extension.html).

    Maybe creating standards is becoming more difficult? Too many parties involved? Too much at stake?

    I have to admit that JMS remains limited to the java space. Maybe one day we will have SOAP/AMQP (http://www.amqp.org). I'm hoping on it.

    Authored by: Jeroen

    Saturday, January 2, 2010

    Do it yourself CA

    Recently got questions on testing with certificates. Use self-signed certificates or CA signed certs? And how to easily obtain CA signed certs? It was quite a while ago that I had been playing with certs myself. So time to refresh my mind, do some searching + experimenting, and write a blog entry about it.

    CA signed certificates (SSL server and client) are recommended as only the CA cert needs to be imported as a trusted certificate (e.g. in cacerts). First option is to use a free CA like CAcert.

    Second option is to setup your own (test) CA. The most obvious option is to use openssl. The command line tool of openssl allows to first create a CA keypair + CA self-signed cert and next sign certificate requests (CSR), thereby creating CA signed certificates.

    Alternative tools for a do-it-yourself CA with GUI are:
    Played around a bit with this SimpleAuthority, and it looks quite OK. One can import certficate signing requests and export signed cert. A very limited version is free, but to manage an unlimited number of certificates, the cost is $50 (personal) to $240 (commercial). The ease-of-use and consistency of the GUI could be improved, but it does do the job.

    Notes:
    • To generate and manage keystores, thé recommended tools is Portecle.
    • Alternative is Keytool IUI: it has extra features such as signing of files, but less user friendly than Portecle.
    • All sorts of links about PKI
    Authored by: Guy