Java Crypto Catchup

Read the original article: Java Crypto Catchup


In 2017, we started a blog series talking about how to securely implement a crypto-system in java. How to Get Started Using Java Cryptography Securely touches upon the basics of Java crypto, followed by posts around various crypto primitives Cryptographically Secure Pseudo-Random Number Generator (CSPRNG), Encryption/Decryption, and Message Digests. We also released a Java Crypto Module for easier dockerization of injectable modules exposing Crypto services via an API.

The last time we spoke about this, we were in Java 8 world. In just 3.5 years we have 7 new Java versions released! Let’s revive this series by first catching up on the latest and greatest happenings in the wider cryptographic community and how that maps to newer Java versions in this post. In the following posts, we will be talking about how to securely write some of the more commonly used cryptographic schemes.

Special thanks to my awesome coworkers Jess Garrett and Andrew Shelton for contributing important sections in this post.

TL;DR

Generic to entire Java Cryptography Architecture (JCA)

Looking at what we discussed in How to Get Started Using Java Cryptography Securely post, the central theme of Java Cryptography Architecture (JCA)[11]ツ?defining abstract engine classes for different cryptographic services and having independent implementations thru different providers hasn’t changed.

Highlighting the most notable changes in JCA:

1. Probably the best enhancement for lazy people like me would be that we no longer need to include the Unlimited strength jurisdiction file. Unlimited strength in algorithms (for example using 256 key sizes for symmetric algorithms) comes out of the box. It is enabled by default in theツ?java.security file, with property crypto.policy=unlimited.
2. The security configuration file (java.security) will now be found under theツ?$JAVA_HOME/Contents/Home/conf/security/ folder.
3. Third party provider jar files are now treated as libraries rather than extensions. Thus, like any other library jar files, provider jar files will be placed on $CLASSPATH, and not as extensions under $JAVA_HOME/Contents/Home/jre/lib/ext folder.

Secure Random

As we discussed in theツ?CSPRNG post, Java already provides algorithms (*PRNG) to safely generate a CSPRNG. To add support for the NIST specified[13] algorithms, Java provides a new algorithm named DRBG.

Why Should You Use DRBG?

The primary reason to use DRBG is that it is government standardized. Also, the DRBG algorithm specification provides more granular configurations of how the underlying algorithm should work. It still sources entropy from the underlying operating system, in case you were wondering.

HowTo: Design and Code It

Some of the extra algorithm-specific configurations and our recommendations are:

  • DRBG mechanism: Underlying mechanism being used should be either Hash or HMAC. Defaults to Hash_SHA256, which is perfectly safe.
  • Security Strength: Default is 128 bits, can be increased.
  • Prediction Resistance: In an event, if the internal state of CSPRNG is compromised, future DRBG outputs won’t be impacted. Enable this.
  • Reseeding: This will periodically reseedツ?to avoid too many outputs from a single seed. Enable this.
  • Personalization String: This is a recommended but not required hardcoded string, which plays a role while seeding but not while adding entropy.

All this can be configured using DrbgParameter.

The most secure way to configure a SecureRandom object using DRBGツ?the algorithm would be:

SecureRandom drbgSecureRandom = SecureRandom.getInstance("DRBG" , 
       DrbgParameters.instantiation(256,  // Required security strength
            PR_AND_RESEED,  // configure algorithm to provide prediction resistance and reseeding facilities
            "any_hardcoded_string".getBytes() // personalization string, used to derive seed not involved in providing entropy.
        )
    );

Refer: Complete code example of Secure Random using DRBG

Encryption/Decryption

There are some exciting advances in Java Cryptography since version 8, and also in the cryptographic community at large since we last spoke about this in Encryption/Decryption. With Java it is usually about adding support for newer and shinier algorithms (ChaCha20, Elliptic Curves) which is great, but rarely about deprecating insecure (DES, RC2, etc.) algorithms.

Symmetric Encryption

It’s 2020 and most of our data is going to be online. To safeguard ourselves against any chosen cipher text attacks, we should only be focused on using Authenticated Encryption schemes. Java offers twoツ?authenticated encryption schemes: AES-GCM and ChaCha20-Poly1305. Let’s see what’s going on with each of these:

AES-GCM Cipher Scheme

We spoke in length about this in our encryption/decryption post. The only thing that changed since then is how we specify the padding scheme.

Internally, GCM mode is basically a stream cipher where padding is not relevant. Transformation string definition is made consistent with throwing an exception for any other padding except NoPadding[3]. Thus,

// This is the only transformation string that would work.
// AES/GCM/PKCS5Padding will throw an exception.
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

Refer: Complete working example of AES-GCM

ChaCha20-Poly1305 Cipher Scheme

Why another Authenticated Encryption Cipher Scheme?

While AES-GCM is the gold standard in authenticated symmetric encryption, imagine a world where, due to advances in cryptoanalysis, AES is broken. This would mean theツ?internet and several other protocols (Bluetooth, Wi-Fi, etc.) would be broken and the worst world won’t even have a fully vetted backup plan. Luckily, the wider industry is preparing for such a standby cipher by adopting ChaCha20 stream cipher[14].

One other reason for ChaCha20-Poly1305 adoption would be its speed. To run faster AES needs dedicated hardware, which is not always possible in smaller, lower-cost hardware devices such as IoT or smartphones.

Google, Cloudflare, and major browsers such as Chrome and Firefox are already using this in their TLS protocols[17,18].

HowTo: Design and Code It?

It is nice to see Java providing Authenticated Encryption cipher construction out of the box in terms of theツ?ChaCha20-Poly1305 algorithm. With this scheme, we can encrypt data of up to 256 GB. This is sufficient enough for any online communication needs but may not work for file/disk encryptions.

HowTo: Chooseツ?the Right Algorithm and Authenticator?

AES is a block cipher, where the mode of operation and padding parameters are relevant. ChaCha20 is a stream symmetric cipher, where these parameters are not relevant. In AES, using GCM mode provides authentication. In ChaCha20 ciphers, Poly1305 provides authenticator services. Accordingly, the transformation string to be used is as under:

Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305");

HowTo: Generate Keys?

Symmetric Keys are still generated with theツ?KeyGenerator class using theツ?ChaCha20ツ?algorithm. Keys should be 256 bits long. Thus,

KeyGenerator keyGenerator = KeyGenerator.getInstance("ChaCha20") ; // Key generator initialized to generate a Symmetric key for use with ChaCha20 algorithm
keyGenerator.init(256 , new SecureRandom); // Generate a 256 bit key
SecretKey chachaKey = keyGenerator.generateKey(); // Generate and store it in SecretKey

HowTo: Configure the Initialization Vector

Just like AES-GCM mode, we would need to get into transparent specifications using IvParameterSpec to configure the initialization vector. Chacha20 ciphers need an initialization vector of size 96 bits (12 bytes).

byte iv[] = new byte[12]; // 96 bits IV for ChaCha20, byte array needs size in terms of bytes.
SecureRandom secRandom = ecureRandom.getInstance("DRBG" , 
                    DrbgParameters.instantiation(256, PR_AND_RESEED, "any_hardcoded_string".getBytes()));
secRandom.nextBytes(iv); // DRBG SecureRandom initialized using self-seeding
IvParameterSpec chachaSpec = new IvParameterSpec(iv);

Refer: Complete working example of ChaCha20-Poly1305

Asymmetric Encryption

A big leap here is support for elliptic curve cryptography (ECC) for various asymmetric encryption applications. This comes with out-of-the-box, clean, and simplified API support served on a silver platter.

Why Is the Industry Even Moving Towards Embracing Elliptic Curves?

Well, RSA has for decades been the defacto algorithm used in asymmetric cryptographic applications,ツ?such as key agreement protocols and digital signing. However, despite its popularity, RSA is a bit fragile which makes its usage more nuanced than it might initially appear. Subtle complexities in generating prime numbers make it difficult to use RSA library implementations securely. Additionally, it has been subject to numerous well-documented padding oracle attacks over the years, many of which continue to impact modern systems[19].

ECC has been around the block for the past 25 years, providing promising cryptoanalysis and future-proofing our applications. Over the years, many curves have been proposed and implemented. Not all are secure. We will discuss which are secured and should be used and which to avoid.

If you are using RSA don’t lose sleep over it, but perhaps validate your code against Encryption/Decryption post. For any new applications, we would strongly encourage using ECC-based APIs.

Let’s briefly look at some of the most commonly used public key applications whose APIs are enhanced by later JDK versions:

Digital Signature

In addition to the already matured support for NIST approved elliptic curves, I am most excited about Edward curves support in Java 15 for Digital Signatures as well as Key Agreement engine classes. We will talk in detail about secure ways of using Digital Signatures in a dedicated upcoming post.

If you are too eager, you can refer to complete working examples of using Digital Signatures using Edward curves and NIST curves.

Key Agreement

Key Agreement engine class is equipped with ECC implementations of its classic counterparts protocols of Diffie Hellman and MQV. It comes with support for NIST curves in ECDH and ECMQV algorithms and Edward Curves in XDH, X25519, & X448 algorithms.

Encryption/Decryption

JDK does provide support for encrypting using elliptic curves thru support for ECIES (Integrated Encryption Scheme). This is sort of a hybrid algorithm between symmetric-asymmetric mechanisms. Elliptic Curves for encryption/decryption is rarely used due to its limitation around the amount of data it can safely handle at a time.

Hashing

In addition to what we discussed in ourツ?Message Digests, aka Hashing Functions post, the SHA3 Family of algorithms are now government approved hashing algorithms. These are not to be viewed as a replacement of SHA2 family algorithms despite the naming. There is nothing insecure about the SHA2 family.

Support for SHA3 algorithms is provided by MessageDigest engine class. You can refer to the complete code of using SHA3 algorithms for computing Message Digests.

At this point, we cobbled together notable enhancements in the last 3.5 years of Java releases. You can experiment with various secure Java Cryptography Libraries being discussed in this series. Going forward, we will just be focusing on the latest version. Next, we will start discussing different cryptographic applications using these building blocks. Keep watching this space!

TL;DR

  • No extra configurations or setup is required for using Unlimited Strength cryptographic algorithms.
  • Security Configuration file (java.security) would be located under theツ?$JAVA_HOME/Contents/Home/conf/security/ folder.
  • Third party provider jar files should be placed on $CLASSPATH.
  • Support

    […]


    Read the original article: Java Crypto Catchup

    Liked it? Take a second to support IT Security News on Patreon!
    Become a patron at Patreon!