All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.structurizr.encryption.AesEncryptionStrategy Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
package com.structurizr.encryption;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;

/**
 * This is implementation of an AES encryption strategy, allowing you to specify the
 * key size, iteration count and passphrase.
 */
public final class AesEncryptionStrategy extends EncryptionStrategy {

    private static final String CIPHER_SPECIFICATION = "AES/CBC/PKCS5PADDING";
    private static final int INITIALIZATION_VECTOR_SIZE_IN_BYTES = 16;

    private int keySize;
    private int iterationCount;
    private String salt;
    private String iv;

    AesEncryptionStrategy() {
    }

    public AesEncryptionStrategy(String passphrase) {
        this(128, 1000, passphrase);
    }

    public AesEncryptionStrategy(int keySize, int iterationCount, String passphrase) {
        super(passphrase);

        this.keySize = keySize;
        this.iterationCount = iterationCount;

        byte[] saltAsBytes = new byte[keySize / 8];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(saltAsBytes);
        this.salt = DatatypeConverter.printHexBinary(saltAsBytes);

        byte[] ivAsBytes = new byte[INITIALIZATION_VECTOR_SIZE_IN_BYTES];
        SecureRandom prng = new SecureRandom();
        prng.nextBytes(ivAsBytes);
        this.iv = DatatypeConverter.printHexBinary(ivAsBytes);
    }

    public AesEncryptionStrategy(int keySize, int iterationCount, String salt, String iv, String passphrase) {
        super(passphrase);

        this.keySize = keySize;
        this.iterationCount = iterationCount;
        this.salt = salt;
        this.iv = iv;
    }

    public String encrypt(String plaintext) throws Exception {
        SecretKey secretKey = createSecretKey();

        Cipher cipher = Cipher.getInstance(CIPHER_SPECIFICATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(DatatypeConverter.parseHexBinary(iv)));

        byte[] byteDataToEncrypt = plaintext.getBytes();
        byte[] byteCipherText = cipher.doFinal(byteDataToEncrypt);

        return Base64.getEncoder().encodeToString(byteCipherText);
    }

    public String decrypt(String ciphertext) throws Exception {
        SecretKey secretKey = createSecretKey();

        Cipher cipher = Cipher.getInstance(CIPHER_SPECIFICATION);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(DatatypeConverter.parseHexBinary(iv)));
        byte[] unencrypted = cipher.doFinal(Base64.getDecoder().decode(ciphertext));

        return new String(unencrypted, "UTF-8");
    }

    private SecretKey createSecretKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec spec = new PBEKeySpec(getPassphrase().toCharArray(), DatatypeConverter.parseHexBinary(salt), iterationCount, keySize);
        return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
    }

    public int getKeySize() {
        return keySize;
    }

    public int getIterationCount() {
        return iterationCount;
    }

    public String getSalt() {
        return salt;
    }

    public String getIv() {
        return iv;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy