Upload
siddharth-coontoor
View
15
Download
3
Embed Size (px)
Citation preview
EAI Endorsed Transactions on _________________
02 -04 2015 | Volume 1 | Issue __ | e_
EAI Endorsed Transactions on Security in Java Editorial
1 Security in Java
Security in Java
Abstract
The intention of this tutorial paper is to explore security in Java that would cover the different services that Java has to
offer in cryptography. The tutorial paper would also explore Java APIs like Java Cryptography architecture (JCA) and Java
cryptography extension (JCE) with comparison of the java.security and java.crypto packages. This paper includes an end
to end demonstration of secret key algorithm (DES) and public key encryption algorithm (RSA) with code snippets and
console outputs.
1.0 Introduction
Java is the foundation for virtually every type of
networked application and is the global standard for
developing and delivering enterprise software, web-based
content, games and mobile applications. Java enjoys a
large and mature ecosystem with strong tools support.
Java delivers application portability and robust
performance across many computing environments. It is
also a growing need to ensure information and application
security by enforcing some security mechanisms to keep
information secure. The java platform also designed to
improve the security of the Java applications.
When correctly implemented the Java security services
can address issues by minimizing security threats faced by
enterprise like authentication, authorization, data
integrity, confidentiality and non-repudiation.
The Java platform includes these services by enforcing
constraints through the use of the Java Virtual Machine
(JVM), a security manager that sandboxes untrusted code
from the rest of the operating system, and a suite of
security APIs that Java developers can utilize.
Several built-in security mechanisms are operating as Java
virtual machine bytecodes. Whenever the program uses an
object reference, the JVM watches. If the program
attempts to cast a reference to a different type, the JVM
makes sure the cast is valid. If the program accesses an
array, the JVM ensures the element the program is
requesting actually exists within the bounds of the array.
If the program tries to use a null reference, the JVM
throws an exception. This helps make Java programs
robust, but also makes their execution more secure.
The Security Manager is a single Java object that
performs runtime checks on dangerous methods. Code in
the Java library consults the Security Manager whenever a
potentially dangerous operation is attempted. The Security
Manager can veto the operation by generating a
SecurityException. Decisions made by the Security
Manager take into account the origin of the requesting
class. Obviously, built-in classes are usually given more
privilege than classes loaded across the Net. The Security
Manager makes the final decision as to whether a
particular operation is permitted or rejected. The security
manager is a class (java.lang.SecurityManager) that
allows applications to implement a security policy. It
allows an application to determine, before performing a
possibly unsafe or sensitive operation, what the operation
is and whether it is being attempted in a security context
that allows the operation to be performed. The application
can allow or disallow the operation.
Java platform includes a large set of APIs, tools, and
implementations of commonly used security algorithms,
mechanisms, and protocols. The Java security APIs span a
wide range of areas, including cryptography, public key
infrastructure, and secure communication, authentication,
and access control. Java security technology provides the
developer with a comprehensive security framework for
writing applications, and also provides the user or
administrator with a set of tools to securely manage
applications.
2.0 Cryptography APIs in Java
Apart from the services provided by JVM and Security
manager that are infused in the Java language to provide
application security, the developers can make use of a
wide array of APIs that this platform has to offer like Java
Authentication and Authorization Service (JAAS),Java
Secure Socket Extension (JSSE), Java GSS-API, Java
SASL API,X.509 Certificate API and Certificate
Revocations Lists (CRLs),Java Cryptography
Architecture(JCA) of which would be discussed in the
following section in detail.
2.1. Security APIs: A detailed look
The Security API in Java can be classified in to five broad
categories in order to list their services. They are of the
following:
Platform Security
The following built-in language security features are
enforced by the Java compiler and virtual machine:
Siddharth Coontoor
2
Strong data typing
Provides a safe and secure platform for developing and
running applications.
Automatic memory management
Compile-time data type checking and automatic memory
management leads to more robust code and reduces
memory corruption and vulnerabilities.
Bytecode verification
Bytecode verification ensures code conforms to the JVM
specification and prevents hostile code from corrupting
the runtime environment.
Secure class loading
Class loaders ensure that untrusted code cannot interfere
with the running of other Java programs.
Cryptography The Java Cryptography Architecture (JCA) and Java
Cryptography Extension (JCE) provide support for a wide
range of cryptographic services including digital
signatures, message digests, ciphers which include
symmetric, asymmetric, stream and block, message
authentication codes, key generators and key factories.
They also support for a wide range of standard algorithms
including RSA, DSA, AES, Triple DES, SHA, PKCS#5,
RC2, and RC4.
Authentication and Access Control
Java Authentication and Authorization Service (JAAS) is
an abstract authentication API that can incorporate a wide
range of login mechanisms through a pluggable
architecture. Policy implementation and Syntax provides a
comprehensive policy and permissions that allows the
developer to create and administer applications requiring
fine-grained access to security-sensitive resources.
Signature Stamp Support API enables single sign-on of
multiple authentication mechanisms and fine-grained
access to resources based on the identity of the user or
code signer. Recent support (in JDK 5) for time stamped
signatures makes it easier to deploy signed code by
avoiding the need to re-sign code when the signer's
certificate expires.
Secure Communications
The Java Secure Socket Extension (JSSE), Java GSS-API
(JGSS) and Java SASL API provide implementations for
the standards-based secure communications protocols:
Transport Layer Security (TLS), Secure Sockets Layer
(SSL), Kerberos which can be accessible through GSS-
API and the Simple Authentication and Security Layer
(SASL).These APIs also provide full support for HTTPS
over SSL/TLS. They also authenticate peers over an
untrusted network and protect the integrity and privacy of
data transmitted between them.
Public key Infrastructure (PKI) The API eases the development and deployment of
complex PKI applications by providing tools for
managing keys and certificates and comprehensive,
abstract APIs with support for the following features and
algorithms:
Certificates and Certificate Revocation Lists (CRLs):
X.509
Certification Path Validators and Builders: PKIX
On-line Certificate Status Protocol (OCSP)
KeyStores: PKCS#11, PKCS#12
Certificate Stores (Repositories) like LDAP,
java.util.Collection
Recent support (in JDK 5) for OCSP provides a more
scalable and timely method for applications to check
certificate revocation status.
2.2. Design Principles
The Java platform defines a set of APIs spanning major
security areas, including cryptography, public key
infrastructure, authentication, secure communication, and
access control. These APIs allow developers to easily
integrate security into their application code. The Java
Cryptography APIs were designed around the following
principles:
Implementation Independence
Applications do not need to implement security
themselves. Rather, they can request security services
from the Java platform. Security services are implemented
in providers, which are plugged into the Java platform via
a standard interface. An application may rely on multiple
independent providers for security functionality.
Implementation Interoperability
Providers are interoperable across applications.
Specifically, an application is not bound to a specific
provider, and a provider is not bound to a specific
application. Implementation interoperability means that
various implementations can work with each other, use
each other's keys, or verify each other's signatures. This
would mean, for example, that for the same algorithms, a
key generated by one provider would be usable by
another, and a signature generated by one provider would
be verifiable by another.
Security in java
3
Algorithm Extensibility
The Java platform includes a number of built-in providers
that implement a basic set of security services that are
widely used today. However, some applications may rely
on emerging standards not yet implemented, or on
proprietary services. The Java platform supports the
installation of custom providers that implement such
services.
Algorithm Independence
The developer can use cryptographic services, such as
digital signatures and message digests, without worrying
about the implementation details or even the algorithms
that form the basis for these concepts
2.3. Cryptography API Architecture
Java provides cryptographic functionalities using two
APIs. The Java Cryptography Architecture (JCA) and the
Java Cryptography Extension (JCE). The JCA is a
security framework that is integrated with core Java API.
The JCE provides extensions for strong encryptions.
The Java platform follows a provider based (pluggable)
architecture. A provider is the underlying implementation
of a particular security mechanism. There are several
providers, some of which are freely available and others
that are quite costly. Companies that offer providers
include IBM, Bouncy Castle, and RSA. The below figure
demonstrates how applications make use of providers that
are included in the java. Security and javax.crypto
packages.
Figure 1.Layout of Java Cryptography Architecture
A program may simply request a particular type of object
(such as a Signature object) implementing a particular
algorithm (such as DSA) and get an implementation from
one of the installed providers. If desired, a program may
instead request an implementation from a specific
provider. Providers may be updated transparently to the
application, for example when faster or more secure
versions are available. This way implementation
independence is achieved using a provider-based
architecture.
The java.security.Provider is the base class for all security
providers. Each Cryptographic Service Provider (CSP)
contains an instance of this class which contains the
provider's name and lists all of the security
services/algorithms it implements. When an instance of a
particular algorithm is needed, the JCA framework
consults the provider's database, and if a suitable match is
found, the instance is created. Providers contain a package
(or a set of packages) that supply concrete
implementations for the advertised cryptographic
algorithms. Each JDK installation has one or more
providers installed and configured by default. Additional
providers may be added statically or dynamically.
To use the JCA, an application simply requests a
particular type of object (such as a MessageDigest) and a
particular algorithm or service (such as the "MD5"
algorithm), and gets an implementation from one of the
installed providers. Alternatively, the program can request
the objects from a specific provider. Each provider has a
name used to refer to it.
md = MessageDigest.getInstance("MD5");
md = MessageDigest.getInstance("MD5", "ProviderC");
Figure 2.Provider based architecture
The figure 2 illustrates requesting an "MD5" message
digest implementation. The figure 2 shows three different
providers that implement various message digest
algorithms ("SHA-1", "MD5", "SHA-256", and "SHA-
512"). The providers are ordered by preference from left
Siddharth Coontoor
4
to right (1-3). In the first illustration, an application
requests an MD5 algorithm implementation without
specifying a provider name. The providers are searched in
preference order and the implementation from the first
provider supplying that particular algorithm, ProviderB, is
returned. In the second figure, the application requests the
MD5 algorithm implementation from a specific provider,
ProviderC. This time the implementation from ProviderC
is returned, even though a provider with a higher
preference order, ProviderB, also supplies an MD5
implementation.
3.0 Comparison between JCA and JCE
The Java Cryptography Architecture (JCA) forms part of
the Java security API, and was first introduced in JDK 1.1
in the java.security package. The Java Cryptography
Extension (JCE) provides a framework and
implementation for encryption, key generation and key
agreement, and Message Authentication Code (MAC)
algorithms. JCE was not a part of the Java Platform prior
to JDK 1.4 and had to be imported separately. From JDK
1.4 onwards the JCE was integrated into the JCA in the
javax.crypto package. The JCE architecture like the JCA
has a provider based architecture allowing new
applications to be added seamlessly. The JCE API
contains many of the advanced cryptographic operations
that were previously under US export control.
The java.security package provides classes and interfaces
for security framework whereas the javax.crypto provides
classes and interfaces for cryptographic operations.
Engine Classes
The classes in JCA/JCE correspond to categories of
cryptographic operations are called engines. An engine
class provides the interface to a specific type of
cryptographic service, independent of a particular
cryptographic algorithm or provider. The engines either
provide cryptographic operations, generators or
converters of cryptographic material or objects that
encapsulate the cryptographic data and can be used at
higher layers of abstraction.
SecureRandom: used to generate random or pseudo-
random numbers.
MessageDigest: used to calculate the message digest
(hash) of specified data.
Signature: initilialized with keys, these are used to sign
data and verify digital signatures.
Cipher: initialized with keys, these used for
encrypting/decrypting data. There are various types of
algorithms: symmetric bulk encryption (e.g. AES, DES,
DESede, Blowfish, IDEA), stream encryption (e.g. RC4),
asymmetric encryption (e.g. RSA), and password-based
encryption (PBE).
Message Authentication Codes (MAC): like
MessageDigests, these also generate hash values, but are
first initialized with keys to protect the integrity of
messages.
KeyFactory: used to convert existing opaque
cryptographic keys of type Key into key specifications
(transparent representations of the underlying key
material), and vice versa.
SecretKeyFactory: used to convert existing opaque
cryptographic keys of type SecretKey into key
specifications (transparent representations of the
underlying key material), and vice versa.
SecretKeyFactorys are specialized KeyFactorys that
create secret (symmetric) keys only.
KeyPairGenerator: used to generate a new pair of public
and private keys suitable for use with a specified
algorithm.
KeyGenerator: used to generate new secret keys for use
with a specified algorithm.
KeyAgreement: used by two or more parties to agree
upon and establish a specific key to use for a particular
cryptographic operation.
AlgorithmParameters: used to store the parameters for a
particular algorithm, including parameter encoding and
decoding.
AlgorithmParameterGenerator: used to generate a set
of AlgorithmParameters suitable for a specified algorithm.
KeyStore: used to create and manage a keystore. A
keystore is a database of keys. Private keys in a keystore
have a certificate chain associated with them, which
authenticates the corresponding public key. A keystore
also contains certificates from trusted entities.
CertificateFactory: used to create public key certificates
and Certificate Revocation Lists (CRLs).
CertPathBuilder: used to build certificate chains (also
known as certification paths).
CertPathValidator: used to validate certificate chains.
.
4.0 Secret Key Encryption Scheme: DES Implementation
The secret key encryption scheme is widely used to
maintain confidentiality of important and sensitive
information when transmitted through network. The Data
Security in java
5
Encryption Standard (DES) is one of such algorithms
used to encrypt the plaintext that contains sensitive
information before it is transmitted through the network.
The DES Algorithm is a secret key algorithm which
means that the security of the encryption scheme depends
upon the secrecy of the key used to encrypt/decrypt the
message. The same key is used for encryption as well as
decryption for which they are also known as symmetric
key encryption schemes.
This section includes an implementation of DES
algorithm using the java.crypto package which comes
under the Java cryptographic Extension (JCE) API.
4.1. Generating the Encryption Key The following code generates a java.security.Key that is a
valid DES algorithm encryption key:
private Key key;
private void generateKey() throws
NoSuchAlgorithmException {
KeyGenerator generator;
generator = KeyGenerator.getInstance("DES");
generator.init(new SecureRandom());
key = generator.generateKey();
}
The method getInstance(String algorithm) of the
javax.crypto.KeyGenerator class, returns
javax.crypto.KeyGenerator objects for the algorithm. The
generator object must then be initialized with a
java.security.SecureRandom that grants secure random
numbers.Finally the secret encryption key can be
generated, this is done using the method generateKey()
that returns the java.security.Key that would be required
to encrypt any message.
4.2. Encrypting the Message
The encryption key that was just generated would now be
used to encrypt the message. The message encryption can
be done in the two steps:
1. Building the Cipher object that will be
responsible of doing the encryption. 2. Then convert the message to a format suitable for
the Cipher. private byte[] encrypt(String message) throws
IllegalBlockSizeException,BadPaddingException,
NoSuchAlgorithmException,NoSuchPaddingException,
InvalidKeyException,UnsupportedEncodingException {
// Get a cipher object.
Cipher cipher =
Cipher.getInstance("DES/ECB/PKCS5Padding")
;
cipher.init(Cipher.ENCRYPT_MODE, key);
// Gets the raw bytes to encrypt, UTF8 is needed
//for having a standard character set
byte[] stringBytes = message.getBytes("UTF8");
// encrypt using the cipher
byte[] raw = cipher.doFinal(stringBytes);
return raw;
}
The Cipher Object is first obtained using the
getInstance(String transformation) which returns an
object.
In the above code DES in ECB mode Cipher object is
retrieved and then initialized in the next statement.
The init(int OpMode,Key key) method is used to initialize
the cipher object with the key. The OpMode would be
“ENCRYPT_MODE” as the message has to be encrypted.
In order to encrypt the message the message has to be first
converted to byte array and then using the doFinal(byte[])
method of the Cipher object we would encrypt the
message.
4.2. Decrypting the Message The steps for decrypting the message are equivalent to
doing the encryption steps in the reverse order.
First, obtain a Cipher, same as for the encryption, the
OpMode in this case for the Cipher Object would be
“DECRYPT_MODE”.
private byte[] decrypt(String encrypted) throws
InvalidKeyException,NoSuchAlgorithmException,
NoSuchPaddingException,IllegalBlockSizeException,
BadPaddingException, IOException {
// Get a cipher object.
Cipher cipher =
Cipher.getInstance("DES/ECB/PKCS5Padding")
;
cipher.init(Cipher.DECRYPT_MODE, key);
//decode the message
byte[] messageBytes = cipher.doFinal(raw);
return messageBytes;
}
The complete DES implementation code is provided in
the Appendix A along with the console outputs.
Siddharth Coontoor
6
5.0 Public Key Encryption Scheme : RSA Implementation The RSA(Rivest, Shamir & Adleman) is an asymmetric
encryption, in which a key needed to encrypt data is made
public, but the corresponding key needed to decrypt it is
kept private, for example in a file on the server to which
clients connect. In principle, such a system solves the
problem of how to send a temporary encryption key
securely to the server when opening a secure connection.
RSA encryption and decryption are essentially
mathematical operations. RSA keys actually consist of
numbers involved in this calculation. The public key
consists of the modulus and a public exponent. The
private key consists of that same modulus plus a private
exponent.
5.1. Encrypting the Message
Creating an RSA key pair essentially consists of picking a
modulus, which is based on two random primes intended
to be unique to that key pair, picking a public exponent,
then calculating the corresponding private exponent given
the modulus and public exponent. Java provides the
KeyPairGenerator class for performing this task.
KeyPairGenerator kpg =
KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();
Create an instance of KeyPairGenerator suitable for
generating RSA keys.
Initialise the generator, telling it the bit length of the
modulus that is required.
Call genKeyPair(), which eventually returns a KeyPair
object.
Call getPublic() and getPrivate() on the latter to pull out
the public and private keys.
Here the key length used for RSA encryption is 2048 bits.
There is a need to store the public and private keys
somewhere. Typically, the private key will be placed on
the server, and the public key distributed to clients. To
store the key, what is needed is to pull out the modulus
and the public and private exponents, then write these
numbers to some file(public.key/private.key). The key
specification classes— RSAPublicKeySpec and
RSAPrivateKeySpec have methods for pulling out the
parameters that make up the key. Then, a KeyFactory
allows to translate between Keys and their corresponding
specification.
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub =
fact.getKeySpec(kp.getPublic(),
RSAPublicKeySpec.class);
RSAPrivateKeySpec priv
=fact.getKeySpec(kp.getPrivate(),
RSAPrivateKeySpec.class);
The Java code to perform RSA encryption uses a Cipher
object, just as with DES encryption. However, this
time,initialise the cipher with the public key. Next use a
KeyFactory as before, reversing the process and pull out
the two public key components from the (public.key)file,
wrap an RSAPublicKeySpec object around them, and run
it through a KeyFactory instance to generate a
corresponding Key object.
RSAPublicKeySpec keySpec = new
RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
Then, use this PublicKey object to initialise a Cipher and
encrypt the data. Note that this time, RSA is specified as
the required cipher algorithm. Then,same procedue is
followed as with symmetric encryption: we initialise the
cipher in encryption mode with the key (in this case, the
RSA public key), and call doFinal(), passing in the data to
be encrypted:
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(message);
5.2. Decrypting the Message
The server goes through a very similar process, and the
code is trivially similar to the client's. The server reads in
its modulus and exponent from its private key file
(private.key) and constructs a corresponding
RSAPrivateKeySpec object, using a KeyFactory to
translate it into a PrivateKey. This PrivateKey can then be
used to initialise a Cipher in DECRYPT_MODE.
The complete RSA implementation code is provided in
the Appendix B along with the console outputs.
Appendix A. DES Implementation
DES algorithm has been implemented using two Java files
one for client and second for server.
The client generates a secret key and stores into a file.
Then the client encrypts the message using the key and
sends it to the server over a socket connection. The server
Security in java
7
uses the same key from the file that the client had created
and decrypts the message.
A.1. Screen Shot of Client sending the Cipher Text to Server:
A.2. Screen Shot of Server decrypting the cipher text received from Client:
Appendix B. RSA Implementation
The RSA algorithm has been implemented using the
client server system where the server would generate the
private and public keys and store the modulus and public
component to public.key and the modulus and private
component it into private.key.
The client would build the public key from the public.key
file and encrypt a message then send the cipher text to the
server. The server would build the private key from the
private.key file and then decrypt the message.
B.1. Screen Shot of Client sending the Cipher Text to Server:
B.2. Screen Shot of Server decrypting the cipher text received from Client:
References
[1] http://en.wikipedia.org/wiki/Java_security
[2] http://docs.oracle.com/javaee/6/tutorial/doc/bnbwk.html
[3] http://www.securingjava.com/
[4] http://www.oracle.com/technetwork/java/javase/tech/index
-jsp-136007.html
[5] http://docs.oracle.com/javase/8/docs/technotes/guides/secu
rity/crypto/CryptoSpec.html#Design
[6] http://www.techrepublic.com/article/master-the-basics-of-
java-cryptography-extension-jce/
[7] http://www-
01.ibm.com/support/knowledgecenter/SSYKE2_5.0.0/com
.ibm.java.doc.user.win32.50/security/jce/jce.html
[8] https://docs.oracle.com/javase/7/docs/api/javax/crypto/pac
kage-summary.html
[9] http://docs.oracle.com/javase/7/docs/api/java/security/pack
age-summary.html
[10] http://en.wikipedia.org/wiki/RSA_%28cryptosystem%29
[11] http://en.wikipedia.org/wiki/Data_Encryption_Standard