[Java] Use cryptography in the standard library

List of cryptographic technologies introduced in this article

We have summarized how to handle the following cryptographic techniques in the Java standard library. We will briefly explain each cryptographic technology and introduce an implementation example.

--Symmetric encryption (AES) --Public Key Cryptography (RSA) --One-way hash function (SHA-256) --Message authentication code (HMAC) --Digital signature (RSA + SHA-256) --Diffie-Hellman Key Exchange

The algorithm used in the implementation example is shown in parentheses.

Symmetric cipher

What is symmetric encryption?

Symmetric encryption is a technology that protects the confidentiality of messages. It has the following features.

--The encryption and decryption keys are the same --Processing speed is faster than public key cryptography

How to use symmetric cryptography

Key generation

This is a method for generating a symmetric key (common key).

    public SecretKey generateKey() throws NoSuchAlgorithmException {

        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128);

        return keyGen.generateKey();
    }

Generation of initialization vector

How to generate an initialization vector. The initialization vector is a random bit string that is intended to be used so that different ciphertexts can be obtained each time even if encrypted using the same key.

    public IvParameterSpec generateIV() {

        SecureRandom random = new SecureRandom();
        byte[] iv = new byte[16];
        random.nextBytes(iv);

        return new IvParameterSpec(iv);
    }

Message encryption

How to encrypt a message. Specify the algorithm, block mode, and padding method when acquiring the Cipher instance. See the JavaDoc for the Cipher class for a combination of algorithms, block modes, and padding methods.

    public byte[] encrypto(String plainText, SecretKey key, IvParameterSpec iv) throws GeneralSecurityException {

        //Format:"algorithm/Block mode/Padding method"
        Cipher encrypter = Cipher.getInstance("AES/CBC/PKCS5Padding");
        encrypter.init(Cipher.ENCRYPT_MODE, key, iv);

        return encrypter.doFinal(plainText.getBytes());
    }

Ciphertext decryption

This is the method of decrypting the ciphertext. Specify the algorithm, block mode, and padding method as you did for encryption.

    public String decrypto(byte[] cryptoText, SecretKey key, IvParameterSpec iv) throws GeneralSecurityException {

        //Format:"algorithm/Block mode/Padding method"
        Cipher decrypter = Cipher.getInstance("AES/CBC/PKCS5Padding");
        decrypter.init(Cipher.DECRYPT_MODE, key, iv);

        return new String(decrypter.doFinal(cryptoText));
    }

Public key cryptography

What is public key cryptography?

Public key cryptography is a technology for protecting the confidentiality of messages. It has the following features.

--The encryption and decryption keys are different --Slow processing speed compared to symmetric encryption

How to use public key cryptography

Key generation

This is a method for generating a public key cryptographic key pair (public key / private key pair).

    public KeyPair generateKeyPair() throws NoSuchAlgorithmException {

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2024);

        return keyGen.generateKeyPair();
    }

Obtain the public / private key from the key pair.

    KeyPair keyPair = generateKeyPair();
    PublicKey publickey = keyPair.getPublic();
    PrivateKey privatekey = keyPair.getPrivate();

Message encryption

How to encrypt a message. Encrypt using ** public key **. Specify the algorithm, block mode, and padding method when acquiring the Cipher instance. See the JavaDoc for the Cipher class for a combination of algorithms, block modes, and padding methods.

    public byte[] encrypto(String plainText, PublicKey publickey) throws GeneralSecurityException {

        //Format:"algorithm/Block mode/Padding method"
        Cipher encrypter = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        encrypter.init(Cipher.ENCRYPT_MODE, publickey);

        return encrypter.doFinal(plainText.getBytes());
    }

Ciphertext decryption

This is the method of decrypting the ciphertext. Decrypt using the ** private key **. Specify the algorithm, block mode, and padding method as you did for encryption.

    public String decrypto(byte[] cryptoText, PrivateKey privatekey) throws GeneralSecurityException {

        Cipher decrypter = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        decrypter.init(Cipher.DECRYPT_MODE, privatekey);

        return new String(decrypter.doFinal(cryptoText));
    }

One-way hash function

What is a one-way hash function?

The one-way hash function is a technology for detecting message tampering. It has the following features.

--A fixed-length hash value can be obtained from a message of any length. --It is practically impossible to obtain the original message from the hash value (it takes a very long time)

How to use the one-way hash function

Message hashing

How to hash a message. In Java, the one-way hash function is called "message digest".

    private byte[] hash(String plainText) throws NoSuchAlgorithmException {

        MessageDigest md = MessageDigest.getInstance("SHA-256");

        return md.digest(plainText.getBytes());
    }

Tampering detection

This is a method for detecting tampering. All you have to do is get the hash value again and compare.

    private boolean verify(String plainText, byte[] givenHash) throws NoSuchAlgorithmException {

        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] newHash = md.digest(plainText.getBytes());

        return Arrays.equals(givenHash, newHash);
    }

Message authentication code

What is a message authentication code?

Message authentication code (MAC) is a technology for detecting message tampering and "spoofing". It has the following features.

--Get the MAC value of a message using a common key for the sender and recipient of the message --Fixed length MAC value can be obtained from messages of arbitrary length --It is practically impossible to obtain the original message from the MAC value (it takes a very long time) --Recipient can detect sender "spoofing" --Third parties cannot detect the sender's "spoofing" (the recipient may be "spoofing" to the sender)

How to use message authentication code

Key generation

This is the method for generating the key (common key) for the message authentication code.

    public SecretKey generateKey() throws NoSuchAlgorithmException {

        KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256");

        return keyGen.generateKey();
    }

Get MAC value

How to get the MAC value of a message.

    private byte[] mac(String plainText, SecretKey key) throws GeneralSecurityException {

        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(key);

        return mac.doFinal(plainText.getBytes());
    }

Tampering detection

This is a method for detecting tampering. All you have to do is get the MAC value again and compare.

    private boolean verify(String plainText, SecretKey key, byte[] givenMac) throws GeneralSecurityException {

        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(key);
        byte[] newMac = mac.doFinal(plainText.getBytes());

        return Arrays.equals(givenMac, newMac);
    }

Digital signature

What is a digital signature?

Digital signatures are a technology for detecting message tampering and "spoofing". It has the following features.

--Use different keys for message sender and recipient --Recipient can detect sender "spoofing" --Third parties can detect "spoofing" of the sender --The public / private key of public key cryptography is used in reverse.

How to use digital signatures

Key generation

How to generate a digitally signed key pair (public key / private key pair).

    public KeyPair generateKey() throws NoSuchAlgorithmException {

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2024);

        return keyGen.generateKeyPair();
    }

Obtain the public / private key from the key pair.

    KeyPair keyPair = generateKey();
    PublicKey publickey = keyPair.getPublic();
    PrivateKey privatekey = keyPair.getPrivate();

Sign the message

How to sign a message. Sign using the ** private key **.

    public byte[] sign(String plainText, PrivateKey privatekey) throws GeneralSecurityException {

        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privatekey);
        sign.update(plainText.getBytes());

        return sign.sign();
    }

Signature verification

How to verify your signature. Validate using ** public key **.

    public boolean verify(String plainText, byte[] sign, PublicKey publicKey) throws GeneralSecurityException {

        Signature verify = Signature.getInstance("SHA256withRSA");
        verify.initVerify(publicKey);
        verify.update(plainText.getBytes());

        return verify.verify(sign);
    }

Diffie-Hellman Key Exchange

What is Diffie-Hellman Key Exchange?

Diffie-Hellman key exchange is a technology for securely sharing a common key between the sender and recipient of a message. It has the following features.

--The sender and receiver of the message exchange information and generate a common key based on that information. --Even if a third party eavesdrops on the exchanged information, the third party cannot generate a common key.

Diffie-Hellman key exchange procedure

The procedure for Diffie-Hellman key exchange is complicated, so let's organize the procedure before explaining how to use it in detail. Invite Alice (sender) and Bob (receiver) to appear to explain the procedure.

When Alice and Bob exchange keys, follow the steps below to generate a common key.

    1. Alice generates a large prime number P and a generator G
  1. Send P and G from Alice to Bob
    1. Alice gets secret value X and public value Y Four. Bob gets secret value X and public value Y Five. Alice and Bob exchange public value Y
  2. Alice generates a common key
  3. Bob generates a common key

How to use Diffie-Hellman key exchange

We will explain how to exchange keys according to the procedure explained above.

1. Alice generates a large prime number P and a generator G

First, generate a key pair and get P and G from the key pair.

    //Key pair generation
    public KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DiffieHellman");
        keyGen.initialize(2048);
        return keyGen.generateKeyPair();
    }
    //Get P and G
    KeyPair keyPair = generateKeyPair();

    DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
    DHParameterSpec paramSpec = publicKey.getParams();
    BigInteger p = paramSpec.getP();
    BigInteger g = paramSpec.getG();

In Java, the values of P and G are fixed. See the Java Cryptography Architecture Standard Algorithm Name Documentation for P and G values.

https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/StandardNames.html#algspec Algorithm specifications → DSA key pair generation algorithm → Default values of parameters

2. Send P and G from Alice to Bob

Send P and G from Alice to Bob. At this time, the values of P and G may be seen by a third party. Bob will generate a key pair based on the received P and G.

    public KeyPair generateKeyPair(BigInteger p, BigInteger g) throws GeneralSecurityException {

        DHParameterSpec paramSpec = new DHParameterSpec(p, g);
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DiffieHellman");
        keyGen.initialize(paramSpec);

        return keyGen.generateKeyPair();
    }

3. Alice gets the secret value X and the public value Y

Alice gets the secret value X and the public value Y.

    //Get secret value X
    DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
    BigInteger x = privateKey.getX();

    //Get public value Y
    DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
    BigInteger y = publicKey.getY();

4. Bob gets the secret value X and the public value Y

Bob gets the secret value X and the public value Y. The acquisition method is the same as Alice.

Five. Alice and Bob exchange public value Y

Alice and Bob exchange the published value Y. At this time, the value of Y may be seen by a third party.

6. Alice generates a common key

Alice generates a common key. To generate the common key, use the values of P and G, the public value Y of the other party (Bob), and the private key (DHPrivateKey) of yourself (Alice).

    public SecretKey generateKey(BigInteger p, BigInteger g, BigInteger othersY, DHPrivateKey myPrivateKey)
            throws GeneralSecurityException {

        //Generate the public key of the other party (Bob)
        DHPublicKeySpec publicKeySpec = new DHPublicKeySpec(othersY, p, g);
        KeyFactory keyFactory = KeyFactory.getInstance("DiffieHellman");
        DHPublicKey othersPublicKey = (DHPublicKey) keyFactory.generatePublic(publicKeySpec);

        //Generate a common key using the public key of the other party (Bob) and the private key of yourself (Alice)
        KeyAgreement keyAgreement = KeyAgreement.getInstance("DiffieHellman");
        keyAgreement.init(myPrivateKey);
        keyAgreement.doPhase(othersPublicKey, true);
        SecretKey key = keyAgreement.generateSecret("AES");

        return key;
    }

7. Bob generates a common key

Bob generates a common key. It is generated in the same way as Alice, but uses Alice's public value Y and Bob's private key (DHPrivateKey).

PBE -Password Based Encryption-

What is PBE

PBE is a technology for protecting confidentiality using passwords. It has the following features.

--The encryption and decryption keys are the same --Generate key from password

How to use PBE

Salt generation

Prepare the salt before generating the key. Salt is a random byte array. Salt is used to prevent passwords from being cracked by dictionary attacks.

    public byte[] generateSalt() {
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[8];
        random.nextBytes(salt);

        return salt;
    }

Key generation

This is the method for generating the PBE key (common key). Specify the password, salt, and the number of hashes. By increasing the number of hashes, you can increase the processing time required for brute force attacks.

    public SecretKey generateKey(String password, byte[] salt, int hashCount) throws GeneralSecurityException {

        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, hashCount);
        SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_128");
        SecretKey key = keyFac.generateSecret(keySpec);

        keySpec.clearPassword();

        return key;
    }

Saving algorithm parameters

Get the algorithm parameters as a byte array and save. Values such as initialization vector are stored in the algorithm parameters.

    private byte[] getAlgorithmParameters(SecretKey key) throws GeneralSecurityException, IOException {

        Cipher encrypter = Cipher.getInstance("PBEWithHmacSHA256AndAES_128");
        encrypter.init(Cipher.ENCRYPT_MODE, key);
        AlgorithmParameters params = encrypter.getParameters();

        return params.getEncoded();
    }

Message encryption

How to encrypt a message. Specify the common key and algorithm parameters.

    public byte[] encrypto(String plainText, SecretKey key, byte[] algParam)
            throws GeneralSecurityException, IOException {

        AlgorithmParameters params = AlgorithmParameters.getInstance("PBEWithHmacSHA256AndAES_128");
        params.init(algParam);

        Cipher encrypter = Cipher.getInstance("PBEWithHmacSHA256AndAES_128");
        encrypter.init(Cipher.ENCRYPT_MODE, key, params);

        return encrypter.doFinal(plainText.getBytes());
    }

Ciphertext decryption

This is the method of decrypting the ciphertext. Specify the common key and algorithm parameters.

    public String decrypto(byte[] cryptoText, SecretKey key, byte[] algParam)
            throws GeneralSecurityException, IOException {

        AlgorithmParameters params = AlgorithmParameters.getInstance("PBEWithHmacSHA256AndAES_128");
        params.init(algParam);

        Cipher decrypter = Cipher.getInstance("PBEWithHmacSHA256AndAES_128");
        decrypter.init(Cipher.DECRYPT_MODE, key, params);

        return new String(decrypter.doFinal(cryptoText));
    }

At the end

Here is a summary of what I learned about cryptography, which is gaining more and more attention due to the rise of blockchain. You can see that Java covers various cryptographic techniques.

Recommended Posts

[Java] Use cryptography in the standard library
Use OpenCV in Java
Use PreparedStatement in Java
Use Java external library for the time being
Try adding text to an image in Scala using the Java standard library
Read standard input in Java
Try global hooking in Java using the JNativeHook library
Use Redis Stream in Java
Code to use when you want to process Json with only standard library in Java
Access the network interface in Java
Guess the character code in Java
Use Microsoft Graph with standard Java
Specify the java location in eclipse.ini
Encrypt using RSA cryptography in Java
Let's use Twilio in Java! (Introduction)
Unzip the zip file in Java
[Java] Do not use "+" in append!
Use composite keys in Java Map.
Use the Findbugs plugin in Eclipse
Welcome to the Java Library Swamp! !!
Parsing the COTOHA API in Java
How to use classes in Java?
Do you use Stream in Java?
Call the super method in Java
Create a simple web server with the Java standard library com.sun.net.httpserver
Get the result of POST in Java
Multilingual Locale in Java How to use Locale
Use OpenCV_Contrib (ArUco) in Java! (Part 2-Programming)
[Java] How to use the File class
Java reference to understand in the figure
[Java] How to use the hasNext function
Try using the Stream API in Java
Call the Windows Notification API in Java
Java Artery-Easy to use unit test library
[Java] How to use the HashMap class
I tried the new era in Java
Studying how to use the constructor (java)
Organized memo in the head (Java --Array)
[Processing × Java] How to use the loop
Try calling the CORBA service in Java 11+
Use "Rhino" which runs JavaScript in Java
Item 72: Favor the use of standard exceptions
What is the main method in Java?
[Processing × Java] How to use the class
How to get the date in java
I tried the AutoValue library in Intellij
[Processing × Java] How to use the function
The story of writing Java in Emacs
Console input in Java (understanding the mechanism)
[Java] Color the standard output to the terminal
[Java] How to use the Calendar class
What wasn't fair use in the diversion of Java APIs on Android
Is it possible to put the library (aar) in the Android library (aar) and use it?
Use JDBC Manager with the settings in jdbc.dicon.
The story of low-level string comparison in Java
[Java] Handling of JavaBeans in the method chain
About the confusion seen in startup Java servers
Introducing the library
The story of making ordinary Othello in Java
[Java] How to use Thread.sleep to pause the program
About the idea of anonymous classes in Java