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

com.tukeof.common.crypto.CipherEnum Maven / Gradle / Ivy

The newest version!
package com.tukeof.common.crypto;

import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.function.BiFunction;

@Slf4j
public enum CipherEnum {
    /**
     * Data Encryption Standard
     * DES: translate 64 bits input to 64-bits encrypted output
     * using a 64-bits secret key
     */
    DES("DES", 56),
    TRIPLE_DES("DESede", 168, 128),
    /**
     * Advanced Encryption Standard
     */
    AES("AES", 128, 192, 256),
    BLOWFISH("Blowfish", 448),
    RC2("RC2", 1024);

    // ==== ==== ==== ====    ==== ==== ==== ====    ==== ==== ==== ====

    private final String ALGORITHM;
    private final int[] KEY_SIZES;
    /**
     * ECB: same input, same output
     * CBC: same input, different output
     */
    private final String ECB_PKCS5_PADDING;
    private final String CBC_PKCS5_PADDING;
    //  NoPadding: input length must be multiple of 16 bytes
    private final String CBC_NO_PADDING;
    private volatile int bufferSize;

    // ---- ---- ---- ----    ---- ---- ---- ----    ---- ---- ---- ----

    /**
     * 

Symmetric cryptographic algorithm

* * @param ALGORITHM Following algorithm * @param KEY_SIZES depends on a the specific algorithm * @see CipherEnum#DES * key size must be equal to 56 * @see CipherEnum#TRIPLE_DES * DESede, key size must be equal to 112 or 168 * @see CipherEnum#AES * key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available * @see CipherEnum#BLOWFISH * key size must be multiple of 8, and can only range from 32 to 448 (inclusive) * @see CipherEnum#RC2 * key size must be between 40 and 1024 bits */ CipherEnum(String ALGORITHM, int... KEY_SIZES) { this.ALGORITHM = ALGORITHM; ECB_PKCS5_PADDING = ALGORITHM + "/ECB/PKCS5Padding"; CBC_PKCS5_PADDING = ALGORITHM + "/CBC/PKCS5Padding"; CBC_NO_PADDING = ALGORITHM + "/CBC/NoPadding"; this.KEY_SIZES = KEY_SIZES; // 4K Buffer Area this.bufferSize = 4096; } public byte[] encryptEcb(byte[] data, byte[] key) throws Exception { return encrypt(data, key, (k, m) -> newCipher(ECB_PKCS5_PADDING, k, m)); } public byte[] encryptEcb(InputStream data, byte[] key) throws Exception { return encrypt(data, key, (k, m) -> newCipher(ECB_PKCS5_PADDING, k, m)); } public int encryptEcb(ByteBuffer input, ByteBuffer output, byte[] key) throws Exception { return encrypt(input, output, key, (k, m) -> newCipher(ECB_PKCS5_PADDING, k, m)); } public byte[] decryptEcb(byte[] data, byte[] key) throws Exception { return decrypt(data, key, (k, m) -> newCipher(ECB_PKCS5_PADDING, k, m)); } public byte[] decryptEcb(InputStream data, byte[] key) throws Exception { return decrypt(data, key, (k, m) -> newCipher(ECB_PKCS5_PADDING, k, m)); } // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- public int decryptEcb(ByteBuffer input, ByteBuffer output, byte[] key) throws Exception { return decrypt(input, output, key, (k, m) -> newCipher(ECB_PKCS5_PADDING, k, m)); } public byte[] encryptCbc(byte[] data, byte[] key) throws Exception { return encrypt(data, key, (k, m) -> newCipherByIv(CBC_PKCS5_PADDING, k, m)); } public byte[] encryptCbc(InputStream data, byte[] key) throws Exception { return encrypt(data, key, (k, m) -> newCipherByIv(CBC_PKCS5_PADDING, k, m)); } public int encryptCbc(ByteBuffer input, ByteBuffer output, byte[] key) throws Exception { return encrypt(input, output, key, (k, m) -> newCipherByIv(CBC_PKCS5_PADDING, k, m)); } public byte[] decryptCbc(byte[] data, byte[] key) throws Exception { return decrypt(data, key, (k, m) -> newCipherByIv(CBC_PKCS5_PADDING, k, m)); } public byte[] decryptCbc(InputStream data, byte[] key) throws Exception { return decrypt(data, key, (k, m) -> newCipherByIv(CBC_PKCS5_PADDING, k, m)); } // ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== public int decryptCbc(ByteBuffer input, ByteBuffer output, byte[] key) throws Exception { return decrypt(input, output, key, (k, m) -> newCipherByIv(CBC_PKCS5_PADDING, k, m)); } public byte[] encryptCbcNoPadding(byte[] data, byte[] key) throws Exception { return encrypt(data, key, (k, m) -> newCipherByIv(CBC_NO_PADDING, k, m)); } public byte[] encryptCbcNoPadding(InputStream data, byte[] key) throws Exception { return encrypt(data, key, (k, m) -> newCipherByIv(CBC_NO_PADDING, k, m)); } // ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== public int encryptCbcNoPadding(ByteBuffer input, ByteBuffer output, byte[] key) throws Exception { return encrypt(input, output, key, (k, m) -> newCipherByIv(CBC_NO_PADDING, k, m)); } public byte[] decryptCbcNoPadding(byte[] data, byte[] key) throws Exception { return decrypt(data, key, (k, m) -> newCipherByIv(CBC_NO_PADDING, k, m)); } public byte[] decryptCbcNoPadding(InputStream data, byte[] key) throws Exception { return decrypt(data, key, (k, m) -> newCipherByIv(CBC_NO_PADDING, k, m)); } // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- public int decryptCbcNoPadding(ByteBuffer input, ByteBuffer output, byte[] key) throws Exception { return decrypt(input, output, key, (k, m) -> newCipherByIv(CBC_NO_PADDING, k, m)); } public byte[] generateKey() { return generateKey(KEY_SIZES[0]); } public byte[] generateKey(int size) { SecretKey secretKey = generateSecretKey(size); return secretKey.getEncoded(); } public SecretKey generateSecretKey(int size) { try { KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM); keyGen.init(size); return keyGen.generateKey(); } catch (NoSuchAlgorithmException e) { log.error(e.getMessage(), e); throw new RuntimeException(e); } } private Cipher newCipher(String transformation, byte[] key, int mode) { try { Cipher cipher = Cipher.getInstance(transformation); SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM); cipher.init(mode, keySpec); return cipher; } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e) { throw new RuntimeException(e.getMessage()); } } private Cipher newCipherByIv(String transformation, byte[] key, int mode) { try { Cipher cipher = Cipher.getInstance(transformation); SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM); // inital vector key = truncKeyForIv(key); IvParameterSpec iv = new IvParameterSpec(key/*, 0, 16*/); cipher.init(mode, keySpec, iv); return cipher; } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException e) { throw new RuntimeException(e.getMessage()); } } private byte[] truncKeyForIv(byte[] key) { if (equals(TRIPLE_DES) || equals(BLOWFISH) || equals(RC2)) { if (key.length != 8) { byte[] newKey = new byte[8]; System.arraycopy(key, 0, newKey, 0, Math.min(key.length, 8)); return newKey; } } return key; } private byte[] encrypt( byte[] data, byte[] key, BiFunction constructor) throws Exception { return crypto(data, key, constructor, Cipher.ENCRYPT_MODE); } private byte[] encrypt( InputStream data, byte[] key, BiFunction constructor) throws Exception { return crypto(data, key, constructor, Cipher.ENCRYPT_MODE); } // ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== private int encrypt( ByteBuffer input, ByteBuffer output, byte[] key, BiFunction constructor) throws Exception { return crypto(input, output, key, constructor, Cipher.ENCRYPT_MODE); } private byte[] decrypt( byte[] data, byte[] key, BiFunction constructor) throws Exception { return crypto(data, key, constructor, Cipher.DECRYPT_MODE); } private byte[] decrypt( InputStream data, byte[] key, BiFunction constructor) throws Exception { return crypto(data, key, constructor, Cipher.DECRYPT_MODE); } private int decrypt( ByteBuffer input, ByteBuffer output, byte[] key, BiFunction constructor) throws Exception { return crypto(input, output, key, constructor, Cipher.DECRYPT_MODE); } private byte[] crypto( byte[] data, byte[] key, BiFunction constructor, int mode) throws Exception { Cipher cipher = constructor.apply(key, mode); return cipher.doFinal(data); } private byte[] crypto( InputStream data, byte[] key, BiFunction constructor, int mode) throws Exception { Cipher cipher = constructor.apply(key, mode); final int size = bufferSize; byte[] buffer = new byte[size]; int readSize; while ((readSize = data.read(buffer)) != -1) { cipher.update(buffer, 0, readSize); } return cipher.doFinal(); } private int crypto( ByteBuffer input, ByteBuffer output, byte[] key, BiFunction constructor, int mode) throws Exception { Cipher cipher = constructor.apply(key, mode); return cipher.doFinal(input, output); } public CipherEnum withBufferSize(int bufferSize) { this.bufferSize = bufferSize; return this; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy