The Java platform strongly emphasizes security, including language safety, cryptography, public key infrastructure, authentication, secure communication, and access control.
The JCA is a major piece of the platform, and contains a "provider" architecture and a set of APIs for digital signatures, message digests (hashes), certificates and certificate validation, encryption (symmetric/asymmetric block/stream ciphers), key generation and management, and secure random number generation, to name a few. These APIs allow developers to easily integrate security into their application code. The architecture was designed around the following principles:
Java Cryptography Architecture :
The JCA (Java Cryptography Architecture) was built around provider architecture. JCA defines and supports a set of APIs for cryptographic services, included in packages java.security, javax.crypto, javax.crypto.spec, and javax.crypto.interfaces. The providers that ship with JDK, such as Sun, SunJCE, SunRsaSign, supply the actual implementations for these APIs. The Oracle Providers Documentation describes technical details of these providers. There are many third-party providers as well, such as bouncy castle and IBMJCE.
This is configured in the security configuration file java.security under your $JAVA_HOME/Contents/Home/jre/lib/security/ location.
If you plan to use one of the external providers, you would need to explicitly install it as per the "Install Providers" section in JCA. Make sure that you are registering a provider in the java.security configuration file, in the required order of priority, and not using the Security.addProvider(). This method adds the provider to the end of the list, so future references to the default provider would most likely never invoke the provider you registered.
Unlimited Strength Jurisdiction Policy :
If you need to use the AES algorithm with a key size larger than 128 bits (as I would recommend), you will need to explicitly install Unlimited Strength Jurisdiction Policy. The default JRE ships with limited strength cryptography.
The following algorithms are available in the SunJCE provider:
Keysize Restrictions : The SunJCE provider uses the following default keysizes (in bits) and enforce the following restrictions:
KeyGenerator
NOTE: The various Password-Based Encryption (PBE) algorithms use various algorithms to generate key data, and ultimately depends on the targeted Cipher algorithm. For example, "PBEWithMD5AndDES" will always generate 56-bit keys.
KeyPairGenerator
AlgorithmParameterGenerator
A transformation is a string that describes the operation (or set of operations) to be performed on the given input, to produce some output. A transformation always includes the name of a cryptographic algorithm (e.g., AES), and may be followed by a feedback mode and padding scheme.
A transformation is of the form: "algorithm/mode/padding" or "algorithm"
Every implementation of the Java platform is required to support the following standard Cipher transformations with the keysizes in parentheses:
Those details are provider specific, and relying on the default mode and padding can be very dangerous(Creating a Cipher Object) If no mode or padding is specified, provider-specific default values for the mode and padding scheme are used.
For example, the SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. This means that in the case of the SunJCE provider: Cipher.getInstance("DES") and Cipher.getInstance("DES/ECB/PKCS5Padding") are equivalent statements.
The javax.crypto.Cipher.getInstance(String transformation) factory method generates Ciphers using transformations of the form algorithm/mode/padding. If the mode/padding are omitted, the SunJCE and SunPKCS11 providers use ECB as the default mode and PKCS5Padding as the default padding for many symmetric ciphers.
It is recommended to use transformations that fully specify the algorithm, mode, and padding instead of relying on the defaults.
Note : ECB works well for single blocks of data and can be parallelized, but generally should not be used for multiple blocks of data.
AES encryption keys (128,192 or 256 bits) and block (128 bits) :
AES Encryption using a SecretKey from KeyStore
The Java KeyStore is a database that can contain keys. A Java KeyStore is represented by the KeyStore (java.security.KeyStore) class. A KeyStore can be written to disk and read again. The KeyStore as a whole can be protected with a password, and each key entry in the KeyStore can be protected with its own password. This makes the KeyStore class a useful mechanism to handle encryption keys securely.
A KeyStore can hold the following types of keys:
Secret keys are used in symmetric encryption. In many cases symmetric keys are negotiated when a secure connection is set up. Therefore you will more often be storing public and private keys in a KeyStore than secret keys.
Creating a KeyStore
You can create a Java KeyStore instance by calling its getInstance() method. Here is an example of creating a KeyStore instance:
Before a KeyStore instance can be used, it must be loaded. KeyStore instances are often written to disk or other kinds of storage for later use. That is why the KeyStore class assumes that you must read its data in before you can use it. However, it is possible to initialize an empty KeyStore instance with no data, as you will see later.
To configure any basic encryption scheme securely, it's very important that all of these parameters (at the minimum) are configured correctly:
Choosing the correct algorithm:
A transformation string always includes the name of a cryptographic algorithm as mentioned in above table. You can use below symmetric and asymmetric algorithms which are actually completely secured.
Symmetric Algorithm: Use AES/AESWrap block cipher;
Asymmetric Algorithm: Use RSA
Choosing the right mode of operation:
Mode of operation, as part of transformation, is only relevant to block ciphers. While using asymmetric ciphers, use ECB as the mode of operation, which essentially is a hack behind-the-scenes, meaning ignore this value. Java providers (SunJCE, SunPKCS11) defaults to ECB mode for symmetric as well as asymmetric algorithms.
Cipher c = Cipher.getInstance("AES");
This defaults to using ECB mode of operation, which should never be used for any cryptographic operations. Plaintext blocks generates identical cipher text blocks. The AES algorithm would be used with ECB mode of operation, making replay attacks very easy.
Using modes such as CFB and OFB, block ciphers can encrypt data in units smaller than the cipher's actual block size. When requesting such a mode, you may optionally specify the number of bits to be processed at a time by appending this number to the mode name as shown in the "AES/CFB8/NoPadding" and "AES/OFB32/PKCS5Padding" transformations. If no such number is specified, a provider-specific default is used. Thus, block ciphers can be turned into byte-oriented stream ciphers by using an 8 bit mode such as CFB8 or OFB8.
Symmetric Algorithms:
Most block cipher modes require the length of plaintext to be a multiple of the block size of the underlying encryption algorithm, which is seldom the case. Thus, we require some padding. Java provides 3 different schemes for just symmetric encryption NOPADDING, PKCS5PADDING and ISO10126PADDING.
Not specifying a padding scheme at all is more dangerous than providing a scheme which is susceptible only to certain types of attacks. It's best to use AEAD mode of operation to be sure that you're protected against these attacks.
Make sure to only use OAEPWith<digest>And<mgf>Padding schemes. For a digest, please use either SHA1 or SHA256/384/512
Choosing the right keys and their sizes :
The security level of an encryption scheme is directly proportional to the size of its key. Key sizes should be long enough that brute force attacks become unfeasible, but short enough to keep computational feasibility in mind.
Symmetric Algorithms (KeyGenerator):
Choose the key size for AES as 256 bits. This is done to future proof your applications.Note: You would still need Java Cryptography Extension (JCE) Unlimited Strength installed to use 256-bit keys.
If you have to choose (or stay with) a 128-bit key size (due to hardware or software limitations), it should be fine from most known attacks, as long as the rest of all the parameters are carefully configured.
Generate an AES key of the desired length (in bits) using KeyGenerator.
Asymmetric Algorithms (KeyPairGenerator):
For asymmetric encryption, choose a key size of at least 2048 bits. if you can afford it (from a hardware and software perspective), use at least 4096 bits key size.
// Generate a RSA key of the desired length (in bits) using KeyPairGenerator .
SecureRandom
The security of basic cryptographic elements largely depends on the underlying random number generator (RNG) that was used. An RNG that is suitable for cryptographic usage is called a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). The strength of a cryptographic system depends heavily on the properties of these CSPRNGs. Depending on how the generated pseudo-random data is applied, a CSPRNG might need to exhibit some (or all) of these properties:
Initialization Vectors:
To add to the complexity of a cipher, Initialization Vectors are used. For CTR and CBC modes of operations, we need IVs to be unpredictable and random. Any randomness needed by Cipher comes from the SecureRandom configuration in init method.
PBKDF2 (Password Based Key Derivation Function) :
PBKDF2 is typically used when only user supplied passwords are used to protect or allow access to secret information, derive cryptographic keying material from sources like a passphrase.
Full Example :
Troubleshooting Security
According to Oracle, if you need to troubleshoot anything related to security, you can use the java.security.debug System property, which contains various options.If you want to monitor security access, you can set the java.security.debug System property. Separate multiple options with a comma. To see a list of all debugging options, use the help setting: java -Djava.security.debug=help
The command java -Djava.security.debug=help will produce help output with the full range of debugging options. Setting the debug level to all is useful when troubleshooting a security-related failure whose cause is completely unknown, but for general use it will produce too much information. A sensible general default is access:failure.
A typical way to use it would be:
java -Djava.security.debug=all TestAESEncryption
Output :
ProviderConfig: Loading provider: sun.security.provider.Sun
Provider: Set SUN provider property [SecureRandom.SHA1PRNG/sun.security.provider.SecureRandom]
Provider: Set SUN provider property [Signature.SHA1withDSA/sun.security.provider.DSA$SHA1withDSA]
Provider: Set SUN provider property [Signature.NONEwithDSA/sun.security.provider.DSA$RawDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.RawDSA/NONEwithDSA]
Provider: Set SUN provider property [Signature.SHA224withDSA/sun.security.provider.DSA$SHA224withDSA]
Provider: Set SUN provider property [Signature.SHA256withDSA/sun.security.provider.DSA$SHA256withDSA]
Provider: Set SUN provider property [Signature.SHA1withDSA SupportedKeyClasses/java.security.interfaces.DSAPublicKey|java.security.interfaces.DSAPrivateKey]
Provider: Set SUN provider property [Signature.NONEwithDSA SupportedKeyClasses/java.security.interfaces.DSAPublicKey|java.security.interfaces.DSAPrivateKey]
Provider: Set SUN provider property [Signature.SHA224withDSA SupportedKeyClasses/java.security.interfaces.DSAPublicKey|java.security.interfaces.DSAPrivateKey]
Provider: Set SUN provider property [Signature.SHA256withDSA SupportedKeyClasses/java.security.interfaces.DSAPublicKey|java.security.interfaces.DSAPrivateKey]
Provider: Set SUN provider property [Alg.Alias.Signature.DSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.DSS/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.SHA/DSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.SHA-1/DSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.SHA1/DSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.SHAwithDSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.DSAWithSHA1/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.OID.1.2.840.10040.4.3/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.1.2.840.10040.4.3/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.1.3.14.3.2.13/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.1.3.14.3.2.27/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.1/SHA224withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.2.16.840.1.101.3.4.3.1/SHA224withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.2/SHA256withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.2.16.840.1.101.3.4.3.2/SHA256withDSA]
Provider: Set SUN provider property [KeyPairGenerator.DSA/sun.security.provider.DSAKeyPairGenerator]
Provider: Set SUN provider property [Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1/DSA]
Provider: Set SUN provider property [Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1/DSA]
Provider: Set SUN provider property [Alg.Alias.KeyPairGenerator.1.3.14.3.2.12/DSA]
Provider: Set SUN provider property [MessageDigest.MD2/sun.security.provider.MD2]
Provider: Set SUN provider property [MessageDigest.MD5/sun.security.provider.MD5]
Provider: Set SUN provider property [MessageDigest.SHA/sun.security.provider.SHA]
Provider: Set SUN provider property [Alg.Alias.MessageDigest.SHA-1/SHA]
Provider: Set SUN provider property [Alg.Alias.MessageDigest.SHA1/SHA]
Provider: Set SUN provider property [MessageDigest.MD5 ImplementedIn/Software]
Provider: Set SUN provider property [MessageDigest.SHA ImplementedIn/Software]
Provider: Set SUN provider property [AlgorithmParameterGenerator.DSA ImplementedIn/Software]
Provider: Set SUN provider property [AlgorithmParameters.DSA ImplementedIn/Software]
Provider: Set SUN provider property [KeyFactory.DSA ImplementedIn/Software]
Provider: Set SUN provider property [SecureRandom.SHA1PRNG ImplementedIn/Software]
Provider: Set SUN provider property [CertificateFactory.X.509 ImplementedIn/Software]
Provider: Set SUN provider property [KeyStore.JKS ImplementedIn/Software]
Provider: Set SUN provider property [CertPathValidator.PKIX ImplementedIn/Software]
Provider: Set SUN provider property [CertPathBuilder.PKIX ImplementedIn/Software]
Provider: Set SUN provider property [CertStore.LDAP ImplementedIn/Software]
Provider: Set SUN provider property [CertStore.Collection ImplementedIn/Software]
Provider: Set SUN provider property [CertStore.com.sun.security.IndexedCollection ImplementedIn/Software]
...
...
ProviderConfig: Loaded provider SUN version 1.8
Provider: SecureRandom.SHA1PRNG algorithm from: SUN
Reference :
https://www.owasp.org/index.php/Using_the_Java_Cryptographic_Extensions
https://www.doc.ic.ac.uk/csg-old/java/jdk6docs/technotes/guides/security/SunProviders.html
https://www.veracode.com/blog/research/encryption-and-decryption-java-cryptography
https://www.veracode.com/blog/research/cryptographically-secure-pseudo-random-number-generator-csprng
https://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html
The JCA is a major piece of the platform, and contains a "provider" architecture and a set of APIs for digital signatures, message digests (hashes), certificates and certificate validation, encryption (symmetric/asymmetric block/stream ciphers), key generation and management, and secure random number generation, to name a few. These APIs allow developers to easily integrate security into their application code. The architecture was designed around the following principles:
- Implementation independence: Applications do not need to implement security algorithms. Rather, they can request security services from the Java platform. Security services are implemented in providers (see below), 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.
- 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.
Java Cryptography Architecture :
The JCA (Java Cryptography Architecture) was built around provider architecture. JCA defines and supports a set of APIs for cryptographic services, included in packages java.security, javax.crypto, javax.crypto.spec, and javax.crypto.interfaces. The providers that ship with JDK, such as Sun, SunJCE, SunRsaSign, supply the actual implementations for these APIs. The Oracle Providers Documentation describes technical details of these providers. There are many third-party providers as well, such as bouncy castle and IBMJCE.
This is configured in the security configuration file java.security under your $JAVA_HOME/Contents/Home/jre/lib/security/ location.
If you plan to use one of the external providers, you would need to explicitly install it as per the "Install Providers" section in JCA. Make sure that you are registering a provider in the java.security configuration file, in the required order of priority, and not using the Security.addProvider(). This method adds the provider to the end of the list, so future references to the default provider would most likely never invoke the provider you registered.
Unlimited Strength Jurisdiction Policy :
If you need to use the AES algorithm with a key size larger than 128 bits (as I would recommend), you will need to explicitly install Unlimited Strength Jurisdiction Policy. The default JRE ships with limited strength cryptography.
The following algorithms are available in the SunJCE provider:
Engine | Algorithm Name(s) | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AlgorithmParameterGenerator
|
DiffieHellman | ||||||||||||||||||||||||
AlgorithmParameters
|
AES,Blowfish,DES,DESede,DiffieHellman,OAEP, PBEWithMD5AndDES,PBEWithMD5AndTripleDES,PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40,RC2 |
||||||||||||||||||||||||
Cipher
|
|
||||||||||||||||||||||||
KeyAgreement
|
DiffieHellman | ||||||||||||||||||||||||
KeyFactory
|
DiffieHellman | ||||||||||||||||||||||||
KeyGenerator
|
AES,ARCFOUR,Blowfish,DES,DESede,HmacMD5, HmacSHA1,HmacSHA256,HmacSHA384,HmacSHA512,RC2 |
||||||||||||||||||||||||
KeyPairGenerator
|
DiffieHellman | ||||||||||||||||||||||||
KeyStore
|
JCEKS | ||||||||||||||||||||||||
Mac
|
HmacMD5,HmacSHA1,HmacSHA256,HmacSHA384,HmacSHA512 | ||||||||||||||||||||||||
SecretKeyFactory
|
DES,DESede,PBEWithMD5AndDES, PBEWithMD5AndTripleDES,PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40,PBKDF2WithHmacSHA1 |
Keysize Restrictions : The SunJCE provider uses the following default keysizes (in bits) and enforce the following restrictions:
KeyGenerator
Alg. Name | Default Keysize | Restrictions/Comments |
---|---|---|
AES | 128 | Keysize must be equal to 128, 192, or 256. |
ARCFOUR (RC4) | 128 | Keysize must range between 40 and 1024 (inclusive). |
Blowfish | 128 | Keysize must be a multiple of 8, ranging from 32 to 448 (inclusive). |
DES | 56 | Keysize must be equal to 56. |
DESede (Triple DES) | 168 | Keysize must be equal to 112 or 168.
A keysize of 112 will generate a Triple DES
key with 2 intermediate keys, and a keysize of 168
will generate a Triple DES key with 3 intermediate keys. Due to the "Meet-In-The-Middle" problem, even though 112 or 168 bits of key material are used, the effective keysize is 80 or 112 bits respectively. |
HmacMD5 | 512 | No keysize restriction. |
HmacSHA1 | 512 | No keysize restriction. |
HmacSHA256 | 256 | No keysize restriction. |
HmacSHA384 | 384 | No keysize restriction. |
HmacSHA512 | 512 | No keysize restriction. |
RC2 | 128 | Keysize must range between 40 and 1024 (inclusive). |
NOTE: The various Password-Based Encryption (PBE) algorithms use various algorithms to generate key data, and ultimately depends on the targeted Cipher algorithm. For example, "PBEWithMD5AndDES" will always generate 56-bit keys.
KeyPairGenerator
Alg. Name | Default Keysize | Restrictions/Comments |
---|---|---|
Diffie-Hellman (DH) | 1024 | Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive). |
AlgorithmParameterGenerator
Alg. Name | Default Keysize | Restrictions/Comments |
---|---|---|
Diffie-Hellman (DH) | 1024 | Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive). |
DSA | 1024 | Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive). |
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");Cipher class provides the functionality of a cryptographic cipher for encryption and decryption. It forms the core of the Java Cryptographic Extension (JCE) framework.In order to create a Cipher object, the application calls the Cipher's getInstance method, and passes the name of the requested transformation to it. Optionally, the name of a provider may be specified.
A transformation is a string that describes the operation (or set of operations) to be performed on the given input, to produce some output. A transformation always includes the name of a cryptographic algorithm (e.g., AES), and may be followed by a feedback mode and padding scheme.
A transformation is of the form: "algorithm/mode/padding" or "algorithm"
Every implementation of the Java platform is required to support the following standard Cipher transformations with the keysizes in parentheses:
- AES/CBC/NoPadding (128)
- AES/CBC/PKCS5Padding (128)
- AES/ECB/NoPadding (128)
- AES/ECB/PKCS5Padding (128)
- DES/CBC/NoPadding (56)
- DES/CBC/PKCS5Padding (56)
- DES/ECB/NoPadding (56)
- DES/ECB/PKCS5Padding (56)
- DESede/CBC/NoPadding (168)
- DESede/CBC/PKCS5Padding (168)
- DESede/ECB/NoPadding (168)
- DESede/ECB/PKCS5Padding (168)
- RSA/ECB/PKCS1Padding (1024, 2048)
- RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
- RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
Cipher cipher = Cipher.getInstance("AES");For Oracle JDK 7 (tested), the default cipher for AES is AES/ECB/PKCS5Padding
Those details are provider specific, and relying on the default mode and padding can be very dangerous(Creating a Cipher Object) If no mode or padding is specified, provider-specific default values for the mode and padding scheme are used.
For example, the SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. This means that in the case of the SunJCE provider: Cipher.getInstance("DES") and Cipher.getInstance("DES/ECB/PKCS5Padding") are equivalent statements.
The javax.crypto.Cipher.getInstance(String transformation) factory method generates Ciphers using transformations of the form algorithm/mode/padding. If the mode/padding are omitted, the SunJCE and SunPKCS11 providers use ECB as the default mode and PKCS5Padding as the default padding for many symmetric ciphers.
It is recommended to use transformations that fully specify the algorithm, mode, and padding instead of relying on the defaults.
Note : ECB works well for single blocks of data and can be parallelized, but generally should not be used for multiple blocks of data.
AES encryption keys (128,192 or 256 bits) and block (128 bits) :
- AES is a new generation cipher that supports key lengths a minimum of 128 and a maximum of 256 bits, each with a fixed block size of 128 bits.
- The differences between AES 128 and AES 256 encryptions are technical. 128-bit algorithm is complex and strong enough to make a cyber attack ineffective in getting access to your valuable personal information. According to the experts’ prediction, AES 128 will be secure and uncrackable for at least the next hundred years or so. It is evident that AES 256 is even stronger.
- For practical purposes, 128-bit keys are sufficient to ensure security. The larger key sizes exist mostly to satisfy some US military regulations which call for the existence of several distinct "security levels", regardless of whether breaking the lowest level is already far beyond existing technology.
- The larger key sizes imply some CPU overhead (+20% for a 192-bit key, +40% for a 256-bit key: internally, the AES is a sequence of "rounds" and the AES standard says that there shall be 10, 12 or 14 rounds, for a 128-bit, 192-bit or 256-bit key, respectively). So there is some rational reason not to use a larger than necessary key
- The size of an AES block is 128 bits, whereas the size of the encryption key can be 128, 192 or 256 bits
import java.security.SecureRandom; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; public class TestAESEncryption { public static void main(String[] args) { String message = "JAVA2DEPTH TEST AES ENCRYPTION DEMO"; try { // Generate an AES key of the desired length (in bits) using an AES KeyGenerator. KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(128); SecretKey secretKey = keyGen.generateKey(); // Get a Cipher instance of the desired algorithm, mode, and padding. Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); // Generate an initialization vector for our message of the same size as the Cipher's blocksize. byte[] iv = new byte[cipher.getBlockSize()]; SecureRandom prng = new SecureRandom(); prng.nextBytes(iv); // Initialize the Cipher instance for encryption using the key and initialization vector. cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); // Use the Cipher to encrypt the message byte[] encrypted = cipher.doFinal(message.getBytes()); // Display encrypted data in readable format using Base64 , readable form can be stored or transmitted. String encryptedData = new String(Base64.getEncoder().encode(encrypted)); System.out.println("Encrypted and encoded message is: "+encryptedData); // Get a new Cipher instance of the same algorithm, mode, and padding used for encryption. Cipher aesCipherForDecryption = Cipher.getInstance("AES/CFB/NoPadding"); // The receiver will now initialize the cipher using the IV and decrypt the ciphertext aesCipherForDecryption.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv)); // Use the Cipher to decrypt the data (readable encrypted should be decoded before decryption) byte[] decrypted = aesCipherForDecryption.doFinal(Base64.getDecoder().decode(encryptedData)); System.out.println("Decrypted text message is: " + new String(decrypted)); } catch (Exception exception) { exception.printStackTrace(); } } }Output:
Encrypted and encoded message is: wKSYTfKykjsnVurq2MAjtjQWAW4c8n33PaJnYcvYQ+bbeEk= Decrypted text message is: JAVA2DEPTH TEST AES ENCRYPTION DEMO
AES Encryption using a SecretKey from KeyStore
The Java KeyStore is a database that can contain keys. A Java KeyStore is represented by the KeyStore (java.security.KeyStore) class. A KeyStore can be written to disk and read again. The KeyStore as a whole can be protected with a password, and each key entry in the KeyStore can be protected with its own password. This makes the KeyStore class a useful mechanism to handle encryption keys securely.
A KeyStore can hold the following types of keys:
- Private keys
- Public keys + certificates
- Secret keys
Secret keys are used in symmetric encryption. In many cases symmetric keys are negotiated when a secure connection is set up. Therefore you will more often be storing public and private keys in a KeyStore than secret keys.
Creating a KeyStore
You can create a Java KeyStore instance by calling its getInstance() method. Here is an example of creating a KeyStore instance:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());This example creates a KeyStore instance of Java's default type. It is also possible to create other types of KeyStore instance by passing a different parameter to the getInstance() method. For instance, here is an example that creates a PKCS12 type KeyStore:
KeyStore keyStore = KeyStore.getInstance("PKCS12");Loading the KeyStore
Before a KeyStore instance can be used, it must be loaded. KeyStore instances are often written to disk or other kinds of storage for later use. That is why the KeyStore class assumes that you must read its data in before you can use it. However, it is possible to initialize an empty KeyStore instance with no data, as you will see later.
Loading the KeyStore data from a file or other storage is done by calling the KeyStore load() method. The load() takes two parameters:
- An InputStream from which to load the KeyStore data.
- A char[] (char array) containing the KeyStore password.
keyStore.load(null, keyStorePassword);You must always load the KeyStore instance, either with data or with null. Otherwise the KeyStore is uninitialized, and all calls to its methods will throw an exception.
import java.security.KeyStore; import java.security.cert.Certificate; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.jpos.iso.ISOUtil; public class KeyStoreAES { private static String keyStorePassword = "Secret Key Store"; private static String keyEntryAlias = "Java2Depth"; public static void main(String[] args) throws Exception { String value = "JAVA2DEPTH TEST AES ENCRYPTION DEMO"; char[] keyStorePasswordInChar = new char[keyStorePassword.length()]; keyStorePassword.getChars(0, keyStorePassword.length(), keyStorePasswordInChar, 0); //Create a SecretKey from KeyGenerator KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); //Create KeyStore and set keyStorePassword KeyStore keyStore = KeyStore.getInstance("JCEKS", "SunJCE"); keyStore.load(null, keyStorePasswordInChar); //Store the SecretKey into KeyStore using key Alias SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Certificate[] chain = new Certificate[1]; keyStore.setKeyEntry(keyEntryAlias, skeySpec, keyStorePasswordInChar, chain); //Read SecretKey from KeyStore and Use it for Encryption/Decryption SecretKey secretKey = (SecretKeySpec) (keyStore.getKey(keyEntryAlias, keyStorePasswordInChar)); //Do Encryption System.out.println("########################ECB#######################"); System.out.println("Key in Hex: " + ISOUtil.byte2hex(secretKey.getEncoded())); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] encryptedData = cipher.doFinal(value.getBytes()); System.out.println("Encrypted Data in Hex :" + ISOUtil.byte2hex(encryptedData)); //Do Decryption cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] decryptedData = cipher.doFinal(encryptedData); System.out.println("Decrypted Data in Plain :" + new String(decryptedData)); } }Output:
########################ECB####################### Key in Hex: fef5a1534f3f3afdcd1bb6f6f72c08b8 Encrypted Data in Hex :65c3a78cb05d509e20a9e0092604ace3ec9c80303b19cf6e58fadfa17417ae0e34209a1f7916e6a031f571ecb59e56a7 Decrypted Data in Plain :JAVA2DEPTH TEST AES ENCRYPTION DEMO
To configure any basic encryption scheme securely, it's very important that all of these parameters (at the minimum) are configured correctly:
- Choosing the correct algorithm
- Choosing the right mode of operation
- Choosing the right padding scheme
- Choosing the right keys and their sizes
- Correct IV initialization with cryptographically secure CSPRNG
Choosing the correct algorithm:
A transformation string always includes the name of a cryptographic algorithm as mentioned in above table. You can use below symmetric and asymmetric algorithms which are actually completely secured.
Symmetric Algorithm: Use AES/AESWrap block cipher;
Asymmetric Algorithm: Use RSA
Choosing the right mode of operation:
Mode of operation, as part of transformation, is only relevant to block ciphers. While using asymmetric ciphers, use ECB as the mode of operation, which essentially is a hack behind-the-scenes, meaning ignore this value. Java providers (SunJCE, SunPKCS11) defaults to ECB mode for symmetric as well as asymmetric algorithms.
Cipher c = Cipher.getInstance("AES");
This defaults to using ECB mode of operation, which should never be used for any cryptographic operations. Plaintext blocks generates identical cipher text blocks. The AES algorithm would be used with ECB mode of operation, making replay attacks very easy.
Using modes such as CFB and OFB, block ciphers can encrypt data in units smaller than the cipher's actual block size. When requesting such a mode, you may optionally specify the number of bits to be processed at a time by appending this number to the mode name as shown in the "AES/CFB8/NoPadding" and "AES/OFB32/PKCS5Padding" transformations. If no such number is specified, a provider-specific default is used. Thus, block ciphers can be turned into byte-oriented stream ciphers by using an 8 bit mode such as CFB8 or OFB8.
AEAD modes such as GCM/CCM perform all AAD authenticity calculations before starting the ciphertext authenticity calculations. To avoid implementations having to internally buffer ciphertext, all AAD data must be supplied to GCM/CCM implementations (via the updateAAD methods) before the ciphertext is processed (via the update and doFinal methods).
final byte[] nonce = new byte[32]; SecureRandom random = SecureRandom.getInstanceStrong(); random.nextBytes(nonce); GCMParameterSpec spec = new GCMParameterSpec(16 * 8, nonce); SecretKeySpec skeySpec = new SecretKeySpec(keyInByte, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, spec); byte[] encryptedData = cipher.doFinal(input.getBytes());Use a different IV value or Nonce for every encryption:
random = SecureRandom.getInstanceStrong(); random.nextBytes(nonce); spec = new GCMParameterSpec(16 * 8, nonce); skeySpec = new SecretKeySpec(keyInByte, "AES"); cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, spec); encryptedData = cipher.doFinal(input.getBytes());
Note :
- GCM mode has a uniqueness requirement on IVs used in encryption with a given key. When IVs are repeated for GCM encryption, such usages are subject to forgery attacks. Thus, after each encryption operation using GCM mode, callers should re-initialize the cipher objects with GCM parameters which has a different IV value.
- Use Authenticated Encryption with Associated Data (AEAD) mode (For example GCM and CCM). To use an unauthenticated mode, use CBC or CTR with a MAC to authenticate the ciphertext.
Symmetric Algorithms:
Most block cipher modes require the length of plaintext to be a multiple of the block size of the underlying encryption algorithm, which is seldom the case. Thus, we require some padding. Java provides 3 different schemes for just symmetric encryption NOPADDING, PKCS5PADDING and ISO10126PADDING.
Not specifying a padding scheme at all is more dangerous than providing a scheme which is susceptible only to certain types of attacks. It's best to use AEAD mode of operation to be sure that you're protected against these attacks.
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding") ; Cipher c = Cipher.getInstance("AES/CTR/PKCS5Padding") ; Cipher c = Cipher.getInstance("AES/GCM/PKCS5Padding") ; Cipher c = Cipher.getInstance("AES/CCM/PKCS5Padding") ;Asymmetric Algorithms:
Make sure to only use OAEPWith<digest>And<mgf>Padding schemes. For a digest, please use either SHA1 or SHA256/384/512
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding") ; Cipher c = Cipher.getInstance("RSA/None/PKCS1Padding") ; Cipher c = Cipher.getInstance("RSA/NONE/OAEPWithSHA1AndMGF1Padding") ; Cipher c = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding") ; Cipher c = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding") ;
Choosing the right keys and their sizes :
The security level of an encryption scheme is directly proportional to the size of its key. Key sizes should be long enough that brute force attacks become unfeasible, but short enough to keep computational feasibility in mind.
Symmetric Algorithms (KeyGenerator):
Choose the key size for AES as 256 bits. This is done to future proof your applications.Note: You would still need Java Cryptography Extension (JCE) Unlimited Strength installed to use 256-bit keys.
If you have to choose (or stay with) a 128-bit key size (due to hardware or software limitations), it should be fine from most known attacks, as long as the rest of all the parameters are carefully configured.
Generate an AES key of the desired length (in bits) using KeyGenerator.
// Generate a RSA key of the desired length (in bits) using KeyPairGenerator . KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(4096); // key size specified here. KeyPair pair = keyGen.generateKeyPair();
Asymmetric Algorithms (KeyPairGenerator):
For asymmetric encryption, choose a key size of at least 2048 bits. if you can afford it (from a hardware and software perspective), use at least 4096 bits key size.
// Generate a RSA key of the desired length (in bits) using KeyPairGenerator .
//returns an unseeded instance of default RNG algorithm based on most preferred provider from list of providers configured in java.security SecureRandom secRan = new SecureRandom(); byte[] ranBytes = new bytes[20]; secRan.nextBytes(ranBytes); // since, there is no setSeed method called before a call to next* method, self-seeding occursCorrect IV initialization with cryptographically secure CSPRNG :
SecureRandom
The security of basic cryptographic elements largely depends on the underlying random number generator (RNG) that was used. An RNG that is suitable for cryptographic usage is called a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). The strength of a cryptographic system depends heavily on the properties of these CSPRNGs. Depending on how the generated pseudo-random data is applied, a CSPRNG might need to exhibit some (or all) of these properties:
- It appears random
- Its value is unpredictable in advance
- It cannot be reliably reproduced after generation
// Explicitly requesting SHA1PRNG and not relying on default implementation chosen SecureRandom secRan = SecureRandom.getInstance("SHA1PRNG") ; secRan.setSeed(12345) ; // explicitly seeding SHA1PRNG algorithm.Note : On Unix like system, NativePRNG algorithm, configured with seeding from non-blocking entropy source, is returned. On Windows, SHA1PRNG algorithm, which can be self-seeded or explicitly seeded is returned.
final byte[] nonce = new byte[16]; SecureRandom random = SecureRandom.getInstanceStrong(); random.nextBytes(nonce); IvParameterSpec ivSpec = new IvParameterSpec(nonce); String username = "java2depth", password = "Password1", secretID = "BlahBlahBlah" , SALT2 = "deliciously salty"; byte[] key = (SALT2 + username + password + secretID).getBytes("UTF-8"); MessageDigest sha = MessageDigest.getInstance("SHA-1"); key = sha.digest(key); key = Arrays.copyOf(key, 16); // use only first 128 bit //key = Arrays.copyOf(key, 24); // use only first 192 bit //key = Arrays.copyOf(key, 32); // use only first 256 bit
Initialization Vectors:
To add to the complexity of a cipher, Initialization Vectors are used. For CTR and CBC modes of operations, we need IVs to be unpredictable and random. Any randomness needed by Cipher comes from the SecureRandom configuration in init method.
byte[] salt = new byte[8]; new SecureRandom().nextBytes(salt); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec keySpec = new PBEKeySpec("myPassword".toCharArray(), salt, 100, 256);
PBKDF2 (Password Based Key Derivation Function) :
PBKDF2 is typically used when only user supplied passwords are used to protect or allow access to secret information, derive cryptographic keying material from sources like a passphrase.
SecretKey secretKey = keyFactory.generateSecret(keySpec);
Note :
- Padding : PKCS7 padding is actually technically the correct padding name, but Java blew it and called it PKCS5PADDING.Technically, PKCS5 padding only applies to ciphers with a cipher block size of 64-bits, not 128-bits, but both PKCS5 and PKCS7 padding act identically for block sizes <= 255 bits. Be sure to specify the mode explicitly as most JCE providers default to ECB mode, which is not secure! For this example, we are use CFB mode with no padding in order to avoid padding attacks.
- Initialization Vectors (IVs) : The IV must be saved for later decryption and should not be reused for other encryption operations. It can be stored separately or sent along with the encrypted data. Usually, the encrypted data is appended to the IV and the result is encoded then stored or transmitted.
import java.security.SecureRandom; import sun.misc.BASE64Encoder; public class SecureRandomGen { public static void main(String[] args) { try { // Initialize a secure random number generator SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); // Method 1 - Calling nextBytes method to generate Random Bytes byte[] bytes = new byte[512]; secureRandom.nextBytes(bytes); // Print the SecureRandom number by calling nextDouble System.out.println(" Secure Random # generated by calling nextBytes() is " + secureRandom.nextDouble()); // Method 2 - Using setSeed(byte[]) to reseed a Random object int seedByteCount = 10; byte[] seed = secureRandom.generateSeed(seedByteCount); System.out.println(" Seed value is " + new BASE64Encoder().encode(seed)); secureRandom.setSeed(seed); System.out.println(" Secure Random # generated using setSeed(byte[]) is " + secureRandom.nextDouble()); } catch (Exception exception) { exception.printStackTrace(); } } }Output:
Secure Random # generated by calling nextBytes() is 0.8054257648221271 Seed value is 1C2PtzanHl64Uw== Secure Random # generated using setSeed(byte[]) is 0.7807233925756302
Full Example :
import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.Arrays; import java.util.Random; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import org.jpos.iso.ISOUtil; public class TestAES{ public static void main(String[] args) throws Exception { String value = "JAVA2DEPTH TEST AES ENCRYPTION DEMO"; //byte[] keyInByte =getKey1(); // byte[] keyInByte =getKey2(); // byte[] keyInByte = getKey3(); // byte[] keyInByte = getKey4(); byte[] keyInByte = getKey5(); doECBEncrytpion(keyInByte, value); doCBCEncrytpion(keyInByte, value); doCFBEncrytpion(keyInByte, value); doOFBEncrytpion(keyInByte, value); doGCMEncrytpion(keyInByte, value); doCTREncrytpion(keyInByte, value); } private static void doECBEncrytpion(byte[] keyInByte,String value ) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{ System.out.println("########################ECB#######################"); System.out.println("Key in Hex: "+ISOUtil.byte2hex(keyInByte)); SecretKeySpec skeySpec = new SecretKeySpec(keyInByte, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] response = cipher.doFinal(value.getBytes()); System.out.println("Encrypted Data in Hex :"+ISOUtil.byte2hex(response)); } private static void doCBCEncrytpion(byte[] keyInByte,String value ) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException{ System.out.println("########################CBC#######################"); System.out.println("Key in Hex: "+ISOUtil.byte2hex(keyInByte)); SecretKeySpec skeySpec = new SecretKeySpec(keyInByte, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec,new IvParameterSpec(new byte[16])); byte[] response = cipher.doFinal(value.getBytes()); System.out.println("Encrypted Data in Hex :"+ISOUtil.byte2hex(response)); } private static void doGCMEncrytpion(byte[] keyInByte,String value ) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException{ System.out.println("########################GCM#######################"); final byte[] nonce = new byte[32]; SecureRandom random = SecureRandom.getInstanceStrong(); random.nextBytes(nonce); GCMParameterSpec spec = new GCMParameterSpec(16 * 8, nonce); System.out.println("Key in Hex: "+ISOUtil.byte2hex(keyInByte)); SecretKeySpec skeySpec = new SecretKeySpec(keyInByte, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, spec); byte[] response = cipher.doFinal(value.getBytes()); System.out.println("Encrypted Data in Hex :"+ISOUtil.byte2hex(response)); } private static void doCTREncrytpion(byte[] keyInByte,String value ) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException{ System.out.println("########################CTR#######################"); final byte[] nonce = new byte[16]; SecureRandom random = SecureRandom.getInstanceStrong(); random.nextBytes(nonce); IvParameterSpec ivSpec = new IvParameterSpec(nonce); System.out.println("Key in Hex: "+ISOUtil.byte2hex(keyInByte)); SecretKeySpec skeySpec = new SecretKeySpec(keyInByte, "AES"); Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); // cipher.init(Cipher.ENCRYPT_MODE, skeySpec); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec); // If IV then must be 16 bytes byte[] response = cipher.doFinal(value.getBytes()); System.out.println("Encrypted Data in Hex :"+ISOUtil.byte2hex(response)); } private static void doCFBEncrytpion(byte[] keyInByte,String value ) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException{ System.out.println("########################CFB#######################"); byte[] iv = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; IvParameterSpec ivSpec = new IvParameterSpec(iv); System.out.println("Key in Hex: "+ISOUtil.byte2hex(keyInByte)); SecretKeySpec skeySpec = new SecretKeySpec(keyInByte, "AES"); Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); // cipher.init(Cipher.ENCRYPT_MODE, skeySpec); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec); // If IV then must be 16 bytes byte[] response = cipher.doFinal(value.getBytes()); System.out.println("Encrypted Data in Hex :"+ISOUtil.byte2hex(response)); } private static void doOFBEncrytpion(byte[] keyInByte,String value ) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException{ System.out.println("########################OFB#######################"); byte[] iv = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; IvParameterSpec ivSpec = new IvParameterSpec(iv); System.out.println("Key in Hex: "+ISOUtil.byte2hex(keyInByte)); SecretKeySpec skeySpec = new SecretKeySpec(keyInByte, "AES"); Cipher cipher = Cipher.getInstance("AES/OFB/NoPadding"); // cipher.init(Cipher.ENCRYPT_MODE, skeySpec); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec); // If IV then must be 16 bytes byte[] response = cipher.doFinal(value.getBytes()); System.out.println("Encrypted Data in Hex :"+ISOUtil.byte2hex(response)); } private static byte[] getKey1() throws NoSuchAlgorithmException { // Get the KeyGenerator KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); // 192 and 256 bits may not be available //kgen.init(192); // 256 bits may not be available //kgen.init(256); // All bits may be available // Generate the secret key specs. SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] getKey2() throws UnsupportedEncodingException, NoSuchAlgorithmException { String username = "java2depth", password = "Password1", secretID = "BlahBlahBlah" , SALT2 = "deliciously salty"; byte[] key = (SALT2 + username + password + secretID).getBytes("UTF-8"); MessageDigest sha = MessageDigest.getInstance("SHA-1"); key = sha.digest(key); key = Arrays.copyOf(key, 16); // use only first 128 bit //key = Arrays.copyOf(key, 24); // use only first 192 bit //key = Arrays.copyOf(key, 32); // use only first 256 bit return key; } private static byte[] getKey3() throws NoSuchAlgorithmException { KeyGenerator keyGen = KeyGenerator.getInstance("AES"); SecureRandom random = SecureRandom.getInstanceStrong(); //keyGen.init(128, random); //keyGen.init(192, random); keyGen.init(256, random); SecretKey key = keyGen.generateKey(); return key.getEncoded(); } private static byte[] getKey4() throws NoSuchAlgorithmException, InvalidKeySpecException { byte[] salt = new byte[8]; new SecureRandom().nextBytes(salt); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); //KeySpec keySpec = new PBEKeySpec("myPassword".toCharArray(), salt, 100, 128); // KeySpec keySpec = new PBEKeySpec("myPassword".toCharArray(), salt, 100, 192); KeySpec keySpec = new PBEKeySpec("myPassword".toCharArray(), salt, 100, 256); SecretKey tmp = keyFactory.generateSecret(keySpec); return tmp.getEncoded(); } private static byte[] getKey5() throws NoSuchAlgorithmException { Random r = new Random(); int num = r.nextInt(10000); String knum = String.valueOf(num); byte[] knumb = knum.getBytes(); KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(knumb); kgen.init(128, sr); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); return skey.getEncoded(); } }Output:
Key 1: ########################ECB####################### Key in Hex: 02c0837bee3193d6c77359dd52a12c96 Encrypted Data in Hex :682504dc1d8a6faa799db662e87a5c6f1a352434daab1dc265eec185239a1b6e37d45da884c48d6d4be382fc778e9081 ########################CBC####################### Key in Hex: 02c0837bee3193d6c77359dd52a12c96 Encrypted Data in Hex :682504dc1d8a6faa799db662e87a5c6f0c8edeb5dca91f548d042cb006d9bf234c4fc80d984d26702ea92493137d7fb0 ########################CFB####################### Key in Hex: 02c0837bee3193d6c77359dd52a12c96 Encrypted Data in Hex :4af474381f2eb1bb6dcefd1e47f0a9d46898d590298cbb0763fb5c2d08820e2d869d8c ########################OFB####################### Key in Hex: 02c0837bee3193d6c77359dd52a12c96 Encrypted Data in Hex :4af474381f2eb1bb6dcefd1e47f0a9d4ef8513c304fd2bab1d41328f964098bd95a14f ########################GCM####################### Key in Hex: 02c0837bee3193d6c77359dd52a12c96 Encrypted Data in Hex :5910c6d4369739cdaa734c924f03e0ae37ee431d172eda117ac30cdbb2a56255f39139800e3c9187b4e8f5c481825f82eff165 ########################CTR####################### Key in Hex: 02c0837bee3193d6c77359dd52a12c96 Encrypted Data in Hex :49ddd878d1a21988a9dc6dca1a2b20e0cb4960b52db4a968422ff01e35670725ee232a Key 2: ########################ECB####################### Key in Hex: d84caeac28f55031a9df2efa125d7928 Encrypted Data in Hex :a85d9f01db4c504136c21436668357b8598cba79a089efada8bca8c059a3294da08307c9aaa4e98fc5968cf928315e18 ########################CBC####################### Key in Hex: d84caeac28f55031a9df2efa125d7928 Encrypted Data in Hex :a85d9f01db4c504136c21436668357b81008d3c0938c21e883e9e0e805f6c6b8f9da260ac4e791b72da08de47afc14e8 ########################CFB####################### Key in Hex: d84caeac28f55031a9df2efa125d7928 Encrypted Data in Hex :67f0d7ad92f97dd12c92c26d6ff6041b7443604be66fe7251e8e07def6649ff31c3cb4 ########################OFB####################### Key in Hex: d84caeac28f55031a9df2efa125d7928 Encrypted Data in Hex :67f0d7ad92f97dd12c92c26d6ff6041b05e2d35be5e20ff4db73683d89304502cac5ff ########################GCM####################### Key in Hex: d84caeac28f55031a9df2efa125d7928 Encrypted Data in Hex :b65bc8efbf777339a6c9e2009dd4034f875169c27b66ebf56f5832aa9bb2701ff018f50e44d3f2588f5cfb47cc712fdb9d5b62 ########################CTR####################### Key in Hex: d84caeac28f55031a9df2efa125d7928 Encrypted Data in Hex :3f9fc6bde33632aa1953dbb65707c31b87b4562b7799951805485cecdab4d65658384f Key 3: ########################ECB####################### Key in Hex: 9b52c769db5c17dd95a404b5cf38808cc231e790a9fafeb08b39cf096c237c34 Encrypted Data in Hex :5d7e728d3d7aad671940d31205e5e1305d0410ca2a5dac8f745f607e0fc0cb5cf641a56bb81e0faaa9c5f88c6229a86f ########################CBC####################### Key in Hex: 9b52c769db5c17dd95a404b5cf38808cc231e790a9fafeb08b39cf096c237c34 Encrypted Data in Hex :5d7e728d3d7aad671940d31205e5e13044a35ef81d3ca24daae6227546bf0b7cf0c7e0d686b652ee47b7aca6275aebd2 ########################CFB####################### Key in Hex: 9b52c769db5c17dd95a404b5cf38808cc231e790a9fafeb08b39cf096c237c34 Encrypted Data in Hex :4fb00915ad17b8efd47124afc8721cd2d335434f7c33fb3e0589cff9a574ff7d6fd4b0 ########################OFB####################### Key in Hex: 9b52c769db5c17dd95a404b5cf38808cc231e790a9fafeb08b39cf096c237c34 Encrypted Data in Hex :4fb00915ad17b8efd47124afc8721cd250b34aace697b12b100d427880ad4b5f418cab ########################GCM####################### Key in Hex: 9b52c769db5c17dd95a404b5cf38808cc231e790a9fafeb08b39cf096c237c34 Encrypted Data in Hex :f7e645d0d5dbc3946a22bb52221faa0dfea0b270c1011c0d3ffd9267055ac25ebc18fe351a1fa3945e2cd5714cfcb5c2bfb013 ########################CTR####################### Key in Hex: 9b52c769db5c17dd95a404b5cf38808cc231e790a9fafeb08b39cf096c237c34 Encrypted Data in Hex :107872cb0bba18e53336c5bd30cdb957f4690f56fd3ca514d9fdad51f3c483cbb26269 Key 4: ########################ECB####################### Key in Hex: 541578e850a38f9f4fda0e7132890096207a8e982ca8e2796723b88f596bb2ef Encrypted Data in Hex :f7c3ce901782770d775f22007bd17e5d1f0a8c4593c412c2b6b93cb67fdb2979a236a48f9fe59f3d0821ab9c686747f3 ########################CBC####################### Key in Hex: 541578e850a38f9f4fda0e7132890096207a8e982ca8e2796723b88f596bb2ef Encrypted Data in Hex :f7c3ce901782770d775f22007bd17e5d3a4e65080773d21f090ee2c781251c52acaf8ff36e4b8067d17b890b60c92730 ########################CFB####################### Key in Hex: 541578e850a38f9f4fda0e7132890096207a8e982ca8e2796723b88f596bb2ef Encrypted Data in Hex :46b1c0fbbb037060a9d981f708bbd40506ba9be1e284e82ce9fee867c79e250b6bc262 ########################OFB####################### Key in Hex: 541578e850a38f9f4fda0e7132890096207a8e982ca8e2796723b88f596bb2ef Encrypted Data in Hex :46b1c0fbbb037060a9d981f708bbd4056d932e9031893bde01687ddf60bf00e9fd921e ########################GCM####################### Key in Hex: 541578e850a38f9f4fda0e7132890096207a8e982ca8e2796723b88f596bb2ef Encrypted Data in Hex :b49a9b4eba4ff33c4021638544ee9329365d2f3031caa06be0ab14e2cf2ada6228e838b8ecbec134c10e13ace2549e0c07ce40 ########################CTR####################### Key in Hex: 541578e850a38f9f4fda0e7132890096207a8e982ca8e2796723b88f596bb2ef Encrypted Data in Hex :9eb0a0bfd704cad42743d8d7d28b6189acd05d4de3c8efde997f26995631c39772f5e5 Key 5: ########################ECB####################### Key in Hex: 92c02e4dcdae92464ef44f732789f437 Encrypted Data in Hex :6a6d031c5a0749326c90ac5b33959400e72db2cd194665a4330729c1d374294f2d56dc127c61058b7bf111c9e2801dc6 ########################CBC####################### Key in Hex: 92c02e4dcdae92464ef44f732789f437 Encrypted Data in Hex :6a6d031c5a0749326c90ac5b3395940035d4e338563b8a19552dd3a4395bb28740c28e150c79f548e5337e6abf256359 ########################CFB####################### Key in Hex: 92c02e4dcdae92464ef44f732789f437 Encrypted Data in Hex :c5bbcf9a802f172fda413828b245dd6a440a9f49432276d3777897a9c7146f3d2f7ff1 ########################OFB####################### Key in Hex: 92c02e4dcdae92464ef44f732789f437 Encrypted Data in Hex :c5bbcf9a802f172fda413828b245dd6a5d828641abf99f67a5ea5244d11b46d41ee986 ########################GCM####################### Key in Hex: 92c02e4dcdae92464ef44f732789f437 Encrypted Data in Hex :0f41ea1015f8b0728b65efa613cfbd428361ab60020fdd9d7e59ac16fcf8f88cd56ac245ee6de0c3f5b1f6d3fe56c6d39ca4d7 ########################CTR####################### Key in Hex: 92c02e4dcdae92464ef44f732789f437 Encrypted Data in Hex :a4b5f18d1be692ddb01541e9530267f7361a8d5fed2b497ec371477e0d65fdfc5d32a9
Troubleshooting Security
According to Oracle, if you need to troubleshoot anything related to security, you can use the java.security.debug System property, which contains various options.If you want to monitor security access, you can set the java.security.debug System property. Separate multiple options with a comma. To see a list of all debugging options, use the help setting: java -Djava.security.debug=help
The command java -Djava.security.debug=help will produce help output with the full range of debugging options. Setting the debug level to all is useful when troubleshooting a security-related failure whose cause is completely unknown, but for general use it will produce too much information. A sensible general default is access:failure.
Option
|
Description
|
all
|
Turn on all debugging
|
access
|
Print all results from the AccessController.checkPermission method.
You can use the following options with the access option:
·
stack: Include stack
trace
·
domain: Dump all
domains in context
·
failure: Before
throwing exception, dump stack and domain that do not have permission
You can use the following options with the stack and domain options:
·
permission=<classname>:
Only dump output if specified permission is being checked
·
codebase=<URL>:
Only dump output if specified codebase is being checked
|
certpath
|
Turns on debugging for
the PKIX CertPathValidator and CertPathBuilder implementations.
You can use the ocsp option with the certpath option for OCSP
protocol tracing. A hexadecimal dump of the OCSP request and response bytes
is displayed.
|
combiner
|
SubjectDomainCombiner debugging
|
gssloginconfig
|
Java GSS (Generic
Security Services) login configuration file debugging
|
configfile
|
JAAS (Java
Authentication and Authorization Service) configuration file loading
|
configparser
|
JAAS configuration
file parsing
|
jar
|
JAR file verification
|
logincontext
|
LoginContext results
|
policy
|
Loading and granting
permissions with policy file
|
provider
|
Security provider
debugging , engine=<engines> can
be used with the provider option:
The supported values
for <engines> are: Cipher,KeyAgreement,KeyGenerator, KeyPairGenerator, KeyStore,Mac,
MessageDigest,SecureRandom,Signature
|
scl
|
Permissions SecureClassLoader assigns
|
jca
|
JCA engine class
debugging
|
keystore
|
Keystore debugging
|
pkcs11
|
PKCS11 session manager
debugging
|
pkcs11keystore
|
PKCS11 KeyStore
debugging
|
pkcs12
|
PKCS12 KeyStore
debugging
|
securerandom
|
SecureRandom debugging
|
ts
|
Timestamping debugging
|
sunpkcs11
|
SunPKCS11 provider
debugging
|
A typical way to use it would be:
java -Djava.security.debug=all TestAESEncryption
Output :
ProviderConfig: Loading provider: sun.security.provider.Sun
Provider: Set SUN provider property [SecureRandom.SHA1PRNG/sun.security.provider.SecureRandom]
Provider: Set SUN provider property [Signature.SHA1withDSA/sun.security.provider.DSA$SHA1withDSA]
Provider: Set SUN provider property [Signature.NONEwithDSA/sun.security.provider.DSA$RawDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.RawDSA/NONEwithDSA]
Provider: Set SUN provider property [Signature.SHA224withDSA/sun.security.provider.DSA$SHA224withDSA]
Provider: Set SUN provider property [Signature.SHA256withDSA/sun.security.provider.DSA$SHA256withDSA]
Provider: Set SUN provider property [Signature.SHA1withDSA SupportedKeyClasses/java.security.interfaces.DSAPublicKey|java.security.interfaces.DSAPrivateKey]
Provider: Set SUN provider property [Signature.NONEwithDSA SupportedKeyClasses/java.security.interfaces.DSAPublicKey|java.security.interfaces.DSAPrivateKey]
Provider: Set SUN provider property [Signature.SHA224withDSA SupportedKeyClasses/java.security.interfaces.DSAPublicKey|java.security.interfaces.DSAPrivateKey]
Provider: Set SUN provider property [Signature.SHA256withDSA SupportedKeyClasses/java.security.interfaces.DSAPublicKey|java.security.interfaces.DSAPrivateKey]
Provider: Set SUN provider property [Alg.Alias.Signature.DSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.DSS/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.SHA/DSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.SHA-1/DSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.SHA1/DSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.SHAwithDSA/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.DSAWithSHA1/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.OID.1.2.840.10040.4.3/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.1.2.840.10040.4.3/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.1.3.14.3.2.13/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.1.3.14.3.2.27/SHA1withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.1/SHA224withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.2.16.840.1.101.3.4.3.1/SHA224withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.2/SHA256withDSA]
Provider: Set SUN provider property [Alg.Alias.Signature.2.16.840.1.101.3.4.3.2/SHA256withDSA]
Provider: Set SUN provider property [KeyPairGenerator.DSA/sun.security.provider.DSAKeyPairGenerator]
Provider: Set SUN provider property [Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1/DSA]
Provider: Set SUN provider property [Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1/DSA]
Provider: Set SUN provider property [Alg.Alias.KeyPairGenerator.1.3.14.3.2.12/DSA]
Provider: Set SUN provider property [MessageDigest.MD2/sun.security.provider.MD2]
Provider: Set SUN provider property [MessageDigest.MD5/sun.security.provider.MD5]
Provider: Set SUN provider property [MessageDigest.SHA/sun.security.provider.SHA]
Provider: Set SUN provider property [Alg.Alias.MessageDigest.SHA-1/SHA]
Provider: Set SUN provider property [Alg.Alias.MessageDigest.SHA1/SHA]
Provider: Set SUN provider property [MessageDigest.MD5 ImplementedIn/Software]
Provider: Set SUN provider property [MessageDigest.SHA ImplementedIn/Software]
Provider: Set SUN provider property [AlgorithmParameterGenerator.DSA ImplementedIn/Software]
Provider: Set SUN provider property [AlgorithmParameters.DSA ImplementedIn/Software]
Provider: Set SUN provider property [KeyFactory.DSA ImplementedIn/Software]
Provider: Set SUN provider property [SecureRandom.SHA1PRNG ImplementedIn/Software]
Provider: Set SUN provider property [CertificateFactory.X.509 ImplementedIn/Software]
Provider: Set SUN provider property [KeyStore.JKS ImplementedIn/Software]
Provider: Set SUN provider property [CertPathValidator.PKIX ImplementedIn/Software]
Provider: Set SUN provider property [CertPathBuilder.PKIX ImplementedIn/Software]
Provider: Set SUN provider property [CertStore.LDAP ImplementedIn/Software]
Provider: Set SUN provider property [CertStore.Collection ImplementedIn/Software]
Provider: Set SUN provider property [CertStore.com.sun.security.IndexedCollection ImplementedIn/Software]
...
...
ProviderConfig: Loaded provider SUN version 1.8
Provider: SecureRandom.SHA1PRNG algorithm from: SUN
Reference :
https://www.owasp.org/index.php/Using_the_Java_Cryptographic_Extensions
https://www.doc.ic.ac.uk/csg-old/java/jdk6docs/technotes/guides/security/SunProviders.html
https://www.veracode.com/blog/research/encryption-and-decryption-java-cryptography
https://www.veracode.com/blog/research/cryptographically-secure-pseudo-random-number-generator-csprng
https://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html
No comments:
Post a Comment