MT311 (Oct 2004) Java Application Development Java Security, Cryptography, Authentication, PKI, Digital Signature & SSL Tutorial 4
Dec 30, 2015
MT311 (Oct 2004)Java Application Development
Java Security, Cryptography, Authentication, PKI, Digital Signature & SSL
Tutorial 4
Tutor Information
Edmund Chiu (Group 4) Email: [email protected] OR
[email protected] Please begin your email subject with [MT311] Webpage: http://learn.ouhk.edu.hk/~t439934
Security Issues in Java
When a computer is connected to a network, it is not enough to have physical security alone.
– Communication security is a concern when computers communicate across a network
In Java applications, there are two main areas of security issues:
– System security – safety and stability of the computing environment against malicious applications (e.g. virus)
– Information security – the secrecy and integrity of data
Sandbox Model
In early days, Java use a basic security model called the sandbox model
– Local applications are considered as trustable and are granted full access to the system
– Download applets are not trusted and could not use any local resources
It is a quick solution related to downloaded applications at that time, but
– has lots of shortcomings because you can either trust or not trust the entire application/applet
– Cannot prevent a local application downloaded from the Internet from accessing a sensitive file
– Even printing from an applet is impossible
Security Policy Model
In a security policy model, resource can be granted or denied different access independently
– For example, if the resource is a file, you can grant a “read”, “write”, “execute” and “delete” permission
– We can grant different types of permission to the following different resources also
Audio, AWT, Network, Property, Runtime and etc Details are given in the Java Documentation on Security
To provide an even more flexible implementation, Java allows different policies to apply to different application, or even to different invocations of the same application.
Applet Security
Consider an Applet writing a file to your PC– Click Here to view the Applet source code
(AppletSecurityTest.java on course homepage)
By default, Sandbox Model is used– Access denied. A security exception is shown in the
applet
Applying Security Policy in Applet
You local PC needs to release the restriction by specifying a different policy
grant {permission java.io.FilePermission
"AppletSecurityTest.txt", "write";};
– Save the above text as a policy file named “policy.AllowWrite” in you current directory
– View your applet using applet viewer applying the policyappletviewer -J-Djava.security.policy=policy.AllowWrite
AppletSecurity.html
Security Policy
As in the previous example, you can see a policy is identified in the following format:
permission <permission> <target> <action>;
– Permission type (java.io.FilePermission)– The target source (AppletSecurityTest.java)– The action (write)
You can also specifying the permission for applets loaded from a URL specified by the code basegrant codeBase http://java.sun.com/- {
permission java.io.FilePermission “<<ALL FILES>>”, “write”;};grant codeBase http://www.microsoft.com/- {
permission java.io.FilePermission “<<ALL FILES>>”, “read”;};
Using the Policy Tool
To save the time and avoid from making mistakes that will lead to security vulnerabilities, Java provides a GUI tool policytool to manage the policies
Code Signing
We can grant a permission to applets from a particular URL to access our computer
– URL can be hijacked or forged, how can we really know the applet file is from the exact party
Java provides another layer of security called code signing
To apply code signing, you need:– Create a JAR file (Java Archive, which is Java’s mechanism
for bundling multiple files) using jar tool (Details)– Sign it using a Java tool jarsigner. You need a key pair
generated by Java keytool to sign the JAR file (Details)jarsigner <jar_file> <key_file>
Code Signing II
The HTML code to read a jarred applet<applet code = AppletClassName.class
archive=“JarFileNaem.jar”width=XXX height=YYY>
When the runtime loads a JAR file, it verifies if the JAR file has been signed and determine if it can be trusted
– A signed JAR file authenticates the file owner and integrity of the signed files in the JAR archive
– Web browser can apply a standard policy to trust an applet if the applet is signed by a trusted authority
Java Archive (JAR)
What is in a JAR file?– Create by: jar cf <jar_file> <all_files>– Execute by: java –jar myJAR.jar– Can also be viewed, extracted or even executed (Main-Class
header is required in the Manifest file)– After code signing, the JAR files includes the class files, a
fingerprint of the jarred files, code signer’s credentials, expiry date, the manifest and other related information
– Fingerprint is an unique authentication token generated using a one-way hash algorithm – any alteration in code will generate a totally different fingerprint
– Manifest is the directory of the archive – listing the files, the signatures, and other information (like Main-Class)
Cryptography
The main objectives of cryptography are:– Confidentiality – the information cannot be
understood by others whom were not intended– Integrity – the information cannot be altered in the
transition between sender and intended receiver without being detected
– Non-repudiation – sender cannot deny his/her intention of sending/creating a message
– Authentication – the sender and receiver can confirm other’s identity and the origin/destination of the information
Secure Communication
The simplest form of secure communication– Sender and recipient agree on a shared key– Communication is encrypted using the shared key– Only the objective of confidentiality is achieved
Sending a Message Securely
Steps of sending messages achieving all four cryptography objectives
– Encrypt the original message with sender’s secret key Confidentiality and authentication – encryption done using sender’s
secret key– Create a message digest of the message
Integrity – digest is unique to the message– Encrypt the encrypted message and the message digest using
the sender’s secret key Non-repudiation – digest and message were encrypted together
– Encrypt the encrypted message, message digest and the sender’s signature with the recipient's secret key
Authentication and confidentiality – only recipient can decrypt the message
Receiving a Message Securely
Steps of receiving messages in a secured way– Decrypt the package with the recipient’s key– Decrypt the pieces with the sender’s key– Compute the message digest to verify the integrity
of the message– Decrypt the encrypted message using the sender’s
key
Problem in a Secret-Key Algorithm
We require a number of secret keys, one for each step The sender and recipient need to agree on the secret
keys used in steps 1 and 2. The sender and recipient need to give their secret keys
to each other– If sender uses the same key for all recipients, the key in not
secret then. – If sender uses different keys for each recipient, key
management is complex– Key distribution is difficult, especially when the two parties are
previously unknown
Public-Key Algorithm
Each party has a pair of keys– public key – made public to all parties you want to
communicate with– private key – kept confidential– The key pair is generated using mathematical properties of
prime number.– Each key pair is unique – It is difficult to compute the private key from the public key
The key pair has an interesting property– Decrypt (Encrypt(message, privateKey), publicKey) = message– Decrypt (Encrypt(message, publicKey), privateKey) = message
Public-Key Algorithm (cont’d)
How public-key algorithm achieve the objectives– Confidentiality and integrity can be achieved when used with
signatures– Non-refutable – the private key is secret and there is only one
right combination of public/private keys– Authentication – a message that A can read will be encrypted
using A’s public key, only A, who have the respective private key can read the message
Messages in public-key algorithm– Sender: Encrypt( Encrypt(msg, SendPrivKey), RecPubKey)– Recipient: Decrypt( Decrypt(msg, RecPriKey), SendPubKey)
Key distribution problem is solved because public key can be made available publicly.
Symmetric Algorithm (Shared Key)
Public key algorithm uses two different keys for encryption and decryption – we call it an asymmetric algorithm
– Public key algorithm requires a lot of computations– In practical, public key algorithm is used to establish the
identities of the two parties and exchange a session key
Symmetric algorithm (shared key algorithm) use the same key for encryption and decryption
– Decrypt (Encrypt (message,key), key) = message– The session key agreed in the above step is used to encrypt
and decrypt the communication after the initial handshake
Java Cryptography Extension (JCE)
JCE provides cryptographic functions, include– Key generation– Encryption/decryption– Message digest– Certificates and more…
The standard APIs are defined, but the implementation can be substituted
– JDK 1.4.2 includes some service implementation provided by Suns– You can still easily install other cryptography providers
implementation (like IBM’s) to the Java Security API and the implementation should still work
– Advantages: Different algorithm can be used – some may only trust certain cryptographic implementation
Some commonly used Cryptographic Services
SecureRandom – SHA1PRNG KeyGenerator – DES, TripleDES, Blowfish KeyPairGenerator – DSA, RSA, DH MessageDigest – SHA1, MD5 MAC – HmacMD5, HmacSHA1 Signature – SHA1withDSA, SHA1WithRSA CertificateFactory – X509 Cipher – DES, TripleDES, Blowfish KeyAgreement – DH List can be retrieved through Provider class in
java.security package (see ListCSPs.java for details)
Encryption and Decryption
Plain textEncrypt
DecryptCipher text
Encryption Strength
Encryption algorithms are measured by their strength– Example: 64-bit SSL and 128 bit-SSL– Key lengths provide a basic measure of strength when the
same protocol is used 128-bit SSL is 264 stronger than 64-bit SSL Actually, the strength also depends on other factor, e.g.,
randomness of keys
– Key lengths are not comparable when different algorithm is used
In RSA, when not all possible keys are valid, typical RSA keys are 1024-bit or even 2048-bit.
Secret-Key Encryption and Decryption
Most encryption and encryption are based on secret key algorithm
DES (Data Encryption Standard) was the de facto standard until recently
– 56-bit key length– Possible to break a DES encryption by searching all possible
keys – in less than 23 hours using 100,000 computers in 1999– Now, Triple-DES is used by running DES three times using three
different key Newer standard used in US government is AES
(Advanced Encryption Standard)– More extensible algorithm whose strength can be extended by
using different key lengths
Using JCE to Encrypt/Decrypt a Message
Java cryptographic APIs are defined in java.security and javax.crypto pacakges
For a basic encryption, we need a secret key and a cryptographic algorithm
– javax.crypto.SecretKey– javax.crypto.Cipher
To create a SecretKey, – we first need a KeySpec (e.g,
javax.crypto.spec.DESKeySpec), which defines the attributes of the cryptographic key
– KeySpec is then passed to a SecretKeyFactory in which the actual SecretKey object is created
Creating a Secret Key (DES Key)// the key itself as a byte arraybyte[] key = {'a','b','c','d','e','f','g','h'};// create a DESKeySpec for out keyDESKeySpec spec = new DESKeySpec(key);// retrieve a DES SecretKeyFactorySecretKeyFactory factory =
SecretKeyFactory.getInstance("DES");// generate the actual SecretKey objectSecretKey secret = factory.generateSecret(spec);
DES key = 56-bit 7 bytesHowever, it is customary to initialize a 8-byte array and use the lower 7 bytes only (InvalidKeyException if only 7 bytes are input)
The secret key can be printed out by using secret.getEncoded().bytesToHexString()
Creating a Cipher
To create a cipher, you need to specify a right provider and call the getInstance static method from the Cipher class– Cipher c = Cipher.getInstance("DES");
Then, you can initialize the Cipher object to either encrypt or decrypt a message (reinitialize will clear all previous data)– c.init(Cipher.ENCRYPT_MODE, secret);– secret refers to the key you obtained in the secret key factory
Now, you can call the update method to encrypt/decrypt the message (repeatedly call to process multi-parts)– c.update(buffer); // buffer is a byte array
To retrieve the encrypted/decrypted result, you invoke the doFinal method– Byte[] isEncrypted = c.doFinal();
Please refer to API specification for other forms of update/doFinal
Encryption and Decryption Example
DESEncrypt.java Main method
– Open a file, encrypt the contents and write the encrypted data in another file
encrypt method– Create a cipher and initialize it using the secret key in the input
parameter– Encrypt the input byte array and return the encrypted result
makeDESKey method– Create and return a DES cryptographic key according to the given byte
array
DESDecrypt.java Exactly the same as DESEncrypt.java except the Cipher is
initialized to decrypt instead of encrypt
Encrypted Echo Server/Client
The Echo server/client can have a more secured communication by adding DES encryption/decryption– Messages cannot be processed if the key was
wrongly typed
See:– DESEchoServer.java– DESEchoClient.java
AES Encryption and Decryption
In AES, apart from creating the KeySpec, we need to also create a IvParameterSpec for the initialization vector
– Example: IvParameterSpec params = new IvParameterSpec(iVBytes);
We call Cipher's init method with the mode (encrypt/decrypt), keySpec and the parameterSpec:
– Example:cipher.init(Cipher.ENCRYPT_MODE, key, params);
Message Digest
Message digests is used to guarantee the integrity of a message, is also known as a fingerprint or a hash.
A message digest is generated using a mathematical transformation called a hash function
– The resultant message digest is typically fixed length The hash function used to produce message digest
should have the following properties:– Extremely difficult to produce a same message digest from two
different messages – the hash must be one-to-one– Extremely difficult to produce the original message from a
given message digest – the hash must be irreversible The most popular algorithms are SHA1 and MD5.
MD5 Algorithm
MD5 algorithm takes in a message of arbitrary length and produces a 128-bit or 16-byte message digest
MD5 is popular because it is one of the faster message digest algorithm
MD5 ensure a download file has not tampered by providing a MD5 checksum
– After the file is downloaded, MD5 checksum is generated and checked against the original one
In this way, two parties can know the secret without transferring the secret itself
– Example: a password's hash is transferred to a homepage and the hash is checked with the hash stored in the web server
Message Digest in Java
Message digests are encapsulated in the class java.security.MessageDigest
Like Cipher, we create a MessageDigest using getInstance method
MessageDigest md = MessageDigest.getInstance("MD5"); Data can then feed in to the MessageDigest object
using the update methodmd.update(buffer); // buffer is a byte array
The hash is retrieved using the digest methodmd.digest();
See the sample code in MD5.java
SHA1 and Keyed MD5
SHA1 is similar to MD5 but it produces a 160-bit message digest.
Going back to the previous password handling technique– Man-in-the-middle can still impersonate the user without knowing
the actual password To prevent the man-in-the-middle attack, we modify the
protocol to a challenge-and-response authentication– Server sends the client a random string– The client computes the MD5 hash of the random string using
the password as a secret key– Previously computed hash cannot be reused because the string
is randomly generated each time
Message Authentication Code (MAC)
MAC (message authentication code) is similar to a message digest, but with the addition of a secret key.
– In addition to integrity, MAC also ensures the authenticity of the message digest
– MAC still has the same key distribution problem To generate a MD5 MAC, we first create the necessary key from
javax.crypto.KeyGeneratorKeyGenerator kg = KeyGenerator.getInstance("HmacMD5");SecretKey sk = kg.generateKey();
MAC object is then created and initialized using the keyMac mac = Mac.getInstance("HmacMD5"); mac.init(sk);
Data is then feed into the MAC object and the resultant code can be retrieved using doFinal
mac.update(buffer); // buffer is a byte arraybyte[] result = mac.doFinal();
Public-Key Infrastructure (PKI)
Public-key algorithm solve the key distribution issue– Public key is distributed widely– Anyone can send you a message that only you can read– If message was also encrypted with the sender's private key,
you can also verify the identity of the sender– But, how do we know a particular public key really belongs to a
particular person? Instead of distributing the public keys in PKI, the public
keys are distributed as certificates– Certificates should contain enough info to authenticate the
owner and associate the owner of a particular public key– Most popular standards for certificates include X.509 and PGP
Certificate Authorities
How do you know the certificate is authentic– It needs to be signed by a trusted party called the Certificate
Authority (CA) using CA's private key – it validate the integrity and authenticity of the cert.
– To verify a certificate, we check the signature using CA's public key, obtainable from CA's root certificate (self-signed)
CA must guarantee its own private key has not been compromised
All certificate related classes in Java are in java.security.cert package
– java.security.cert.Certificate– java.security.cert.X509Certificate
Keys Management
Keys and certificates can be stored in binary or text files, and in Java, a special format called key store.
To create a key store and generate a certificate, you can invoke keytool as:
keytool –keystore myKeyStore –genKey –alias myKey
– Password is required for the key store– You will also be prompted for the information
necessary for the X.509 certificate
Certificates Management
The certificate created by the recent step can be exported by calling:– For binary file export:
keytool -keystore myKeyStore -storepass <passwd> -alias <myKey> -export –file <file>
– For text format export:keytool -keystore myKeyStore -storepass <passwd>
-alias <myKey> -export –rfc –file <file> The certificates generated by keytool are self-signed
Using Certificate in Java
Import a certificate from a fileFileInputStream is = new FileInputStream(file);
CertificateFactory cf =
CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(is);
Information within the Certificate
Information within a cert is abstracted as Principle– Subject is retrieved by:
Principal p = cert.getSubjectDN(); // p.getName() will return the subject
– Issuer is retrieved by:Principal p = cert.getIssuerDN();// p.getName() will return the issuer name
See ViewCert.java
Verifying the Certificate
To verify the certificate– Get the public key from the cert. (normally from CA's cert):
PublicKey key = cert.getPublicKey();– Verify the certificate using the public key
cert.verify(key); // give out exceptions if verification fails Possible exceptions in a certificate
– NoSuchAlgorithmException– InvalidKeyException– NoSuchProviderException– SignatureException– CertificateException
See ViewCert2.java
Other Certificate Issues
Trust is transitive in most PKI– Certificate can be chained– Once you validate a certificate, you need to validate
all intermediate certificates
Revocation– Certificates that are no longer valid is to be put in
the certificate revocation lists
Comparing Secret-Key and Public-Key Algorithm
Secret-key are much faster than public-key Public key requires certificate authorities as a
trusted third party Secret-key requires pre-agreement on keys
and key distribution using public key is easier (using certificates)
Digital Signature
Secret-key MAC key distribution problem revisit– Can be solved by using private key to generate
MAC and use public key to verify it – too slow– Hash the message and sign using our private key,
the process is called digital signing– Digital signature verifies the identity and integrity of
the message
Digital Signature in Java
In Java, java.security.Signature contains the function used in digital signing
– The most popular algorithm used is Digital Signature Algorithm (DSA)
Key pair is first generated– KeyPairGenerator kpg = new
KeyPairGenerator.getInstance("DSA"); Then, initialize the key generator with the desired length
– kpg.intialize(1024, new SecureRandom()); The key pair can be generated according to followings
– KeyPair keypair = kpg.generateKeyPair();– DSAPublicKey public = (DSAPublicKey) keypair.getPublic());– DSAPrivateKey private = (DSAPrivateKey) keypair.getPrivate());
Digital Signature in Java (cont'd)
The signing processSignature sign = Signature.getInstance("DSA");
sign.initSign(privateKey);
sign.update(buffer);
return sign.sign(); // signature is created
The verifying processSignature sign = Signature.getInstance("DSA");
sign.initVerify(privateKey);
sign.update(buffer);
return sign.verify();
Other Issues on Digital Signature
A DSA algorithm requires a key of at least 1024 bits and the resultant signature is 46-bytes long
Though we can create a DSA for the entire message, it works very slowly.
Thus, it is typical we create a hash for the message first, and use DSA to sign the hash only
Before Starting SSL
Special Notes: Please ignore the Installation Notes in your Course Materials if you use JDK1.4.x. It is for previous versions only.
Secure Socket Layer (SSL)
SSL is the de facto standard for securing communication on the Internet
SSL uses a combination of public key algorithm and symmetric key algorithms to authenticate the parties and secure the communication
– Public key is nice but slow and symmetric key is fast but key distribution is a headache
– When SSL session is started, the tow parties use a public key mechanism to authenticate each other
– Then, they exchange a session key and is used in a symmetric algorithm to encrypt and decrypt the communication
HTTPS Connection to a Website
You can connect a URL with https (in fact invoking SSL communication) – URLConnection urlConn = url.openConnection();
You can test if you can make a HTTPS connection using the given example (SSLTest.java):– java SSLTest <host>– Java –Djavax.net.debug=ssl SSLTest <host>
SSL in Socket Programming
SSL can write socket programs similar to normal socket programs
– Instead of Socket and ServerSocket, SSL uses SSLSocket and SSLServerSocket
– However, SSL Sockets are constructed using the getDefault method in SSLSocketFactory (unless you have other SSL provider)
– After obtaining a SSLSocketFactory (casting the SocketFactory obtained above), you can use the createSocket method to create an SSLSocket
– You need to cast the obtained Socket back to SSLSocketSSLSocketFactory sslSocketFactory =
(SSLSocketFactory) SSLSocketFactory.getDefault();SSLSocket sslSocket = (SSLSocket)
sslSocketFactory.createSocket(server, port);
SSL in Socket Programming (cont'd)
SSLServerSocket can be created in a similar method as in SSLSocket
– First, we retrieve a SSLServerSocketFactory using getDefault method in the class
– Casting back the obtained ServerSocketFactory to SSLServerSocketFactory, we create an SSLServerSocket using the createServerSocket method
SSLServerSocketFactory sslSSFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getFactory();
SSLServerSocket sslSSocket = (SSLServerSocket) sslSSFactory.createServerSocket(port);
SSLSocket sslSocket = (SSLSocket) sslSSocket.accept();
SSL Implementation
SSL protocol only defines the basic mechanisms for handshaking and data exchange
– The public-key and/or secret-key algorithms are not defined
The secret keys, key length and the encryption algorithm are collectively called cipher suites
– You can retrieve the default and supported cipher suites from SSLSocketFactory and SSLServerSocketFactory using the following methods:
String[] getDefaultCipherSuites();
String[] getSupportedCipherSuites();
SSL Communication
Step 1 is to authenticate the two parties– Involves certificate checking– However, SSLSocket and SSLServerSocket has done all
checking for you
Then, the two parties agree on the cipher to use– Cipher suites can be retrieved using methods in SSLSocket
and SSLServerSocket
Other than the above, SSLSocket and SSLServerSocket are the same as Socket and ServerSocket
SSL Echo Server/Client
In order to run the given SSL echo server and client, we need to provide the necessary certificates
In this example, we create a keystore using keytool– keytool –keystore <file> -genkey –alias <keyName>
In a production environment, CA will issue the server certificate and the client will have the lists of root certs and other certs it trusts.
SSL Echo Server/Client
In the server side, we specify the server certificate to use by– java –Djavax.net.ssl.keyStore=<cert file>
-Djavax.net.ssl.keyStorePassword=<passwd> SSLEchoServer
In the client side, we specify a key store for certificates that the clients trust– java –Djavax.net.ssl.trustStore=<trusted cert>
-Djavax.net.ssl.trustStorePassword=<passwd> SSLEchoClient