Java Cryptography

Java Cryptographic Architecture

Java Cryptographic Architecture

Java cryptography software comes in two sections.

JCA

  • The overall design of the cryptography classes is governed by the java cryptography architecture(JCA).

  • The JCA specify design patterns and extensible architecture for defining cryptographic concepts and algorithms.

  • These concepts(interfaces) are encapsulated by java.security and javax.crypto packages.

  • Implementation ares supplied by cryptographic providers.

  • JDK1.2 comes with a default provider, named SUN. which implements a few cryptographic algorithms.

JCE

Java split its cryptography classes into two groups.

  • First group is included in the java.security.* packages that are part of JDK1.2. These classes can be exported without restriction.

  • Second group, the Java Cryptography Extension, is for U.S and Canadian distribution only.

  • JCE is another extension of JCA and includes cryptographic provider called SunJCE.

  • JCD is a standard extension library contains all its classes in java.crypto.* package.

Some classes in java.security are concerned with access control, security policy and permissions. These are not directly related to cryptography.
  • The JCA(Java Cryptography Architecture) includes classes like MessageDigest , SecureRandom , KeyFactory , Signature and KeyStore. Comes with JDK itself.

  • JCE(Java Cryptography Extension) add some more classes of cryptography like Cipher , KeyGeneration , Mac and KeyGeneration. It is the default implementation of JCA provided by JDK itself.

  • PKI (Public key infrastructure) A public key infrastructure is a set of roles, policies, hardware, software and procedures needed to create, manage, distribute, use, store and revoke digital certificates and manage public-key encryption

  • FIPS (Federal Information Processing Standard) 140-2 is the benchmark for validating the effectiveness of cryptographic hardware.

Important classes

Below some of important classes from JCA and JCE

Details
Class or Interface Description

java.security.cert.Certificate

A cryptographic certificate

javax.crypto.Cipher

A cipher

java.security.Key ,java.security.PrivateKey ,java.security.PublicKey ,javax.crypto.SecretKey

A key, used for signing or encryption

javax.crypto.KeyAgreement

A secret key exchange protocol

java.security.KeyFactory

Translates public and private keys from one format to another

javax.crypto.KeyGenerator

Creates keys for symmetric ciphers

java.security.KeyPairGenerator

Creates pairs of public and private keys for signing or encryption

javax.crypto.Mac

A Message Authentication Code (MAC)

java.security.MessageDigest

A cryptographic hash function

javax.crypto.SecretKeyFactory

Translates secret keys from one format to another

java.security.SecureRandom

A cryptographically strong random number engine

java.security.Signature

A digital signature

API and SPI

JCA classes divided into two groups.

  • Application Programming Interface(API): It consists of all public methods that you can use to work with an instance of concept class.

java.security.Signature contains all API methods like verify.
  • Service Provider Interface (SPI): Set of methods that subclasses must implement. SPI methods all begin with engine.

java.security.SignatureSpi contains all SPI methods like engineVerify.
Providers will implement SPI interfaces.

Factory Methods

JCA makes extensive use of factory methods to supply instances.

The following concepts classes have getInstance(algorithm, provider);

Class

javax.crypto.Cipher

javax.crypto.KeyAgreement

java.security.KeyFactory

javax.crypto.KeyGenerator

java.security.KeyPairGenerator

javax.crypto.Mac

java.security.MessageDigest

javax.crypto.SecretKeyFactory

java.security.Signature

Provider Architecture

  • At the root of the JCA is the idea of security providers.

  • A provider supplies algorithms for the cryptographic concept classes.

  • Provider is a collection of algorithms headed up by java.security.Provider.

Configuring Provider

Providers can be configured in two ways.

  • Static Provider Configuration: Edit $JAVA_HOME/jre/lib/security/java.security properties file.

java.security
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.crypto.provider.SunJCE
  • Runtime Provider Configuration: Runtime provider configuration can be done using Security.addProvider() or Security.insertProviderAt().

    • Security class has following important methods to manage providers.

Details
Security.java
class Security{
    /**
     * Adds provider
     * @param provider Provider
     * @return position
    */
    public static int addProvider(Provider provider);
    /**
     * Return Provider instance of given name
     * @param name providerName
     * @return null if name not found
    */
    public static Provider getProvider(String name);
    /**
     * Returns arrays of providers
     * @return array
    */
    public static Provider[] getProviders();
    /**
     *
     * @param provider Provider
     * @param position position
     * @return inserted position, already present return -1
    */
    public static int insertProviderAt(Provider provider, int position);
    /**
     * Remove provider with name
     * @param name providerName
    */
    public static void removeProvider(String name);
}
  • Following Providers available by default in Mac Laptop

Provider Information

SUN

SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS & DKS keystores; PKIX CertPathValidator; PKIX CertPathBuilder; LDAP, Collection CertStores, JavaPolicy Policy; JavaLoginConfig Configuration)

SunRsaSign

Sun RSA signature provider

SunEC

Sun Elliptic Curve provider (EC, ECDSA, ECDH)

SunJSSE

Sun JSSE provider(PKCS12, SunX509/PKIX key/trust factories, SSLv3/TLSv1/TLSv1.1/TLSv1.2)

SunJCE

SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC)

SunJGSS

Sun (Kerberos v5, SPNEGO)

SunSASL

Sun SASL provider(implements client mechanisms for: DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5, NTLM; server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5, NTLM)

XMLDSig

XMLDSig (DOM XMLSignatureFactory; DOM KeyInfoFactory; C14N 1.0, C14N 1.1, Exclusive C14N, Base64, Enveloped, XPath, XPath2, XSLT TransformServices)

SunPCSC

Sun PC/SC provider

Apple

Apple Provider

Random Number Generation

  • Random Numbers are important for strong cryptography.

  • Strong PRNG(Pseudo-random number generation) was introduced in JDK1.1 using java.security.SecureRandom that extends java.util.Random.

Strong PRNG java.security.SecureRandom uses SHA-1 algorithm which produces 20 byte digest.
RandomGeneration.java
public class Main {
    public static void main(String[] args) {

        SecureRandom secureRandom = new SecureRandom(SecureRandom.getSeed(1024));
        byte[] b =new  byte[100];
        secureRandom.nextBytes(b);
        System.out.println(Base64.getEncoder().encodeToString(b));

    }
}

Key Management

To exchange data securely, we need to keep track of our own private and public keys. JCA has support for the key management using Identity and KeyStore classes.

Key Management Concepts included in the following classes and interfaces in the JDK.

Keys

The java.security.Key interface encapsulates a cryptographic key. It defines only three methods.

Key.java
public class Key{
    /**
    * Returns name of cryptographic algorithm for which this key is used.
     * Example: DSA(Digital Signature Algorithm)
     * @return name
    */
    public String getAlgorithm();
    /**
     * Returns encoded value of the key
     * @return value
    */
    public byte[] getEncoded();
    /**
     * Return name of the format used to encode the key. example X.509
     * @return format
    */
    public String getFormat();
}
  • Several interfaces extend this Key interface.

    • java.security.PublicKey: used to verify signature.

verifySignature
Ex: Signature.getInstance("").initVerify(publicKey )
  • java.security.PrivateKey: used to generate the signature

generateSign
Ex: Signature.getInstance("").initSign(privateKey);
  • java.crypto.SecretKey: JCE includes another semantic extension of Key:

This is used for symmetric cipher. same key used for encrypt and decrypt.

  • java.security.KeyPair: encapsulates a matches public and private key.

KeyPair.java
public class KeyPair {
    public PublicKey getPublic();
    public PrivateKey getPrivate();
}

Key Generators

Key Generators are used to create new random keys which has following three steps.

  • Obtain a key generator object for the algorithm you want to use.

  • Initialize the key generator.

  • Ask the key generator to generator a key or key pair.

KeyGenerators.java
import javax.crypto.KeyGenerator;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;

public class KeyGenerators {

    public static void main(String[] args) throws Exception {

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        System.out.println(keyPair.getPrivate());
        System.out.println(keyPair.getPublic());

        KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
        keyGenerator.init(new SecureRandom());
        System.out.println(keyGenerator.generateKey());

    }
}

Algorithm-Specific Initialization

Both KeyPairGenerator and KeyGenerator support the concept of algorithm-specific initialization.

  • Interface java.security.spec.AlgorithmParameterSpec defines no methods os constants. This of it as a box for parameters. you can pass AlgorithmParameterSpec to key generator to initializt it.

Key Translators

To transmit key over network or store on desk, following classes required.

  • SecretKeySpec : simplest way to convert array of bytes to a secret key is the javax.crypto.spec.SecretKeySpec.

SecretKeySpecDemo.java
public class Main {
    public static void main(String[] args) throws Exception {


        SecureRandom secureRandom = new SecureRandom();
        byte[] ke = new byte[20];
        secureRandom.nextBytes(ke);

        SecretKey secretKey = new SecretKeySpec(ke, "HmacSHA1");
        System.out.println(secretKey.getAlgorithm());

    }

    public SecretKey makeDESKey(byte[] input, int offset)
      throws NoSuchAlgorithmException, InvalidKeyException,
      InvalidKeySpecException {
    SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
    KeySpec spec = new DESKeySpec(input, offset);
    return desFactory.generateSecret(spec);
  }

   public byte[] makeBytesFromDESKey(SecretKey key)
      throws NoSuchAlgorithmException, InvalidKeySpecException {
    SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
    DESKeySpec spec =
        (DESKeySpec)desFactory.getKeySpec(key, DESKeySpec.class);
    return spec.getKey();
  }
}
  • SecretKeyFactory: for more complicated translation.

Key Agreement

Key agreement is a protocol whereby two or more parties can agree on a secret value. parties can agree on a secret value even while talking on an insecure medium. These protocol called key agreement protocol.

Diffie-Hellman

Most famous key agreement protocol is Diffie-Hellman(DH).

Message Digests

Message digests are one of the building blocks of digital signatures.

MessageDigest.java
public class MessageDigest {

    public static void main(String[] args) throws Exception {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA");
        messageDigest.update(inputBytes);
        byte[] digest= messageDigest.digest();

    }
}

MAC

A message authentication code(MAC) is basically a keyed message digest.

MAC takes an arbitrary amount of input data and creates a short digest value.

Unlike MessageDigest , MAC uses key to create digest.

MACDemo.java
public class MACDemo {
    public static void main(String[] args) throws Exception {

        SecureRandom sr = new SecureRandom();
        byte[] keyBytes = new byte[20];
        sr.nextBytes(keyBytes);
        SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA1");
        Mac m = Mac.getInstance("HmacSHA1");
        m.init(key);
        m.update(inputData);
        byte[] mac = m.doFinal();

    }
}

Signatures

Signature is a message digest that is encrypted with the Signer’s private key. only public key can decrypt the signature.

If the message digest of the message matches the decrypted message digest from the signature, then integrity is also assured.

A Signature provides two security services.

  • authentication

  • integrity

Certificates

Certificate maintain authority of our secretKeys.

  • Several standards specify the contents of a certificate.

  • One of the most popular is X.509, published by the International Telecommunications Union (ITU).

Block Ciphers

Streams and Blocks

Symmetric ciphers come in two varieties.

  • Block ciphers: encrypt /decrypt fixed size blocks of data, usually 64 bits long

  • Stream ciphers: operate on a stream of bytes.

If you were encrypting the data between the client and server with a block cipher, you’d have to wait until the client typed enough characters to fill a block. In this case, a stream cipher is better suited to the task.
  • Padding: The plaintext you wish to encrypt will not always be a multiple of block size (usually 64 bits). To compensate for the last incomplete block, padding is needed.

    • A padding scheme specifies exactly how the last block of plaintext is filled with data before is encrypted.

    • Corresponding procedure on the decryption side removes the padding and restores the plaintext orighinal length.

PKCS#5 is one possible padding scheme. Fill the remainder of the block with bytes containing the number of remaining bytes.
  • Modes: the mode of cipher determines how blocks of plaintext are encrypted into blocks of ciphertext.

ECB, CBC, CFB, OFB, PCBC modes
cipher
Cipher.getInstance("DES/ECB/PKCS5Padding");

Stream Ciphers

TBD

Encryption Algorithms & Cipher

Name Provider

DES

SunJCE, Cryptix, IAIK, JCP

DESede

SubJCE, Cryptix, IAIK, JCP

PBEWIthMD5AndDES

SunJCE

RSA

Cryptix, IAIK, JSAFE

Blowfish

Cryptix

IDEA

Cryptix

SPEED

Cryptix

Cipher(Encryption)

javax.crypto.Cipher class encrypts and decrypts data.

It encapsulates a cipher algorithm.

It comes in three flavors.

  • Symmetric (singleKey)

  • Asymmetric (two keys)

  • Hybrid systems uses a combination of both.

CipherDemo.java
public class CipherDemo {
    public static void main(String[] args) throws Exception {

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        String inputString = "Codergists";

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
        byte[] raw = cipher.doFinal(inputString.getBytes());
        System.out.println("Encryption successful");

        cipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());
        System.out.println("Decrypted " + new String(cipher.doFinal(raw)));
        System.out.println("Decryption Successful");

    }
}

Feeding Data to a Cipher

A Cipher transforms one block of data into another block of data, either encrypting or decrypting. Two methods, update() and doFinal() , are used to feed data into the Cipher.

There are four overloaded versions of update():

Cipher.java
public interface Cipher{
    /**
    *
     *   This method adds the given array of input data to the Cipher. If the Cipher has accumulated enough data to transform one or more blocks,
     *   it does so,  returning the transformed blocks.
     *   Leftover data that does not fill an entire block is stored for use with the next call to update() or doFinal().
    */
    public final byte[] update(byte[] input) throws IllegalStateException;

    /**
    * This method is the same as above, except that it uses inputLen bytes of the supplied byte array, starting at inputOffset.
    */
    public final byte[] update(byte[] input, int inputOffset, int inputLen) throws IllegalStateException;
    /**
     * This method works like the previous method. The output, however, is written into the supplied output array.
    *   If the output array is too small to hold the results of the call to update(), a ShortBufferException is thrown. This method returns the total number of bytes that were written to the output array.
     */
    public final int update(byte[] input, int inputOffset, int inputLen, byte[] output) throws IllegalStateException, ShortBufferException;

    /**
    *    This method is the same as above, except that the output is written to the given output array, starting at outputOffset. As before, a ShortBufferException is thrown if there’s not enough space in the output array.
    */
    public final int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws IllegalStateException, ShortBufferException;

    public void demo(){
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] plain5 = "comic".getBytes();
        byte[] plain7 = "serious".getBytes();
        byte[] step1 = cipher.update(plain5);
        byte[] step2 = cipher.update(plain7);
    }
}

Let’s see how update() works in practice. In the following examples, assume that we have already obtained a DES key.

The block size of a DES cipher is 8 bytes. In the first call to update(), we pass only 5 bytes, which is not enough for a full block.

  • Thus, no data is returned, and the length of the step1 array is 0. Our next call to update() adds 7 more bytes, for a total of 12.

  • This is enough to encrypt and return 1 block of data.

  • The step2 array is 8 bytes long and contains the first block of ciphertext.

  • What happened to the 4 leftover bytes?

The Cipher is still keeping track of them. * You can encrypt them, if they are the end of the plaintext, with the doFinal() methods.

BouncyCastle Provider

BouncyCastle is a Java library that complements the default Java Cryptographic Extension (JCE).

  • Bouncy Castle Provider (FIPS Distribution): The FIPS 140-2 Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms certified to FIPS 140-2 level 1. This jar contains JCE provider and low-level API for the BC-FJA version 1.0.2.4, FIPS Certificate #4616. Please see certificate for certified platform details.

filename.groovy
// https://mvnrepository.com/artifact/org.bouncycastle/bc-fips
implementation group: 'org.bouncycastle', name: 'bc-fips', version: '1.0.2.4'
  • Bouncy Castle Provider(bcprov-jdk18on): The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for JDK 1.8 and up.

essential.groovy
// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk18on
implementation group: 'org.bouncycastle', name: 'bcprov-jdk18on', version: '1.77'
  • Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs:

The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, and certificate generation. This jar contains APIs for JDK 1.8 and up. The APIs can be used in conjunction with a JCE/JCA provider such as the one provided with the Bouncy Castle Cryptography APIs.

filename.groovy
// https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk18on
implementation group: 'org.bouncycastle', name: 'bcpkix-jdk18on', version: '1.77'
  • Bouncy Castle PKIX APIs (FIPS Distribution):

The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, S/MIME and certificate generation. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified and used appropriately

filename.groovy
// https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-fips
implementation group: 'org.bouncycastle', name: 'bcpkix-fips', version: '1.0.7'

Jipher Provider

Jipher JCE is an Oracle-developed Java Cryptography Architecture (JCA) provider that packages a pre-configured and FIPS compliant version of OpenSSL 3.0.

JipherProvider.java
public class JipherProvider {
    public static void main(String[] args) {

        Security.insertProviderAt(new JipherJCE(), 1);
        Provider provider = Security.getProvider("JipherJCE");

        //print algorithm supported by provider
        System.out.println("-----------Algorithms ------------------");
        provider.getServices().stream()
                .filter(s -> "Cipher".equals(s.getType()))
                .map(Provider.Service::getAlgorithm)
                .forEach(name -> System.out.println(name));

    }
}

Public Key Infrastructure(PKI)

Public key cryptography and PKI are different.

  • Public key cryptography is also referred to as asymmetric cryptography.

  • PKI is an infrastructure for the secure distribution of public keys that are used in public key cryptography.

A PKI system uses symmetric and asymmetric encryption algorithms and digital certificates(X.509) to provide security for multiple applications and uses. The security that is provided through PKI relies on processes and services that are fundamental. These security services allow for a secure solution to be developed for delivery of information across the Internet. The security services are:

  • Confidentiality —Ensuring that only the intended recipient can read the data

  • Integrity —Ensuring the data has not been altered

  • Authentication —Ensuring that a sender and recipient are who they say they are

  • Non-repudiation — Ensuring an originator cannot refute the validity of a statement or document

FIPS 140-2

FIPS (Federal Information Processing Standard) 140-2 is the benchmark for validating the effectiveness of cryptographic hardware. If a product has a FIPS 140-2 certificate you know that it has been tested and formally validated by the U.S. and Canadian Governments.

The FIPS certification standard defines four increasing, qualitative levels of security:

  • Level 1: Requires production-grade equipment and externally tested algorithms.

  • Level 2: Adds requirements for physical tamper-evidence and role-based authentication. Software implementations must run on an Operating System approved to Common Criteria at EAL2.

  • Level 3: Adds requirements for physical tamper-resistance and identity-based authentication. There must also be physical or logical separation between the interfaces by which “critical security parameters” enter and leave the module. Private keys can only enter or leave in encrypted form.

  • Level 4: This level makes the physical security requirements more stringent, requiring the ability to be tamper-active, erasing the contents of the device if it detects various forms of environmental attack.

Comments

Popular posts from this blog

IBM Datapower GatewayScript

Spring boot Kafka Integration

Spring boot SOAP Web Service Performance