Skip to content

Instantly share code, notes, and snippets.

@dfpalomar
Created January 31, 2018 16:18
Show Gist options
  • Save dfpalomar/a82c0a4785635d026f80143da9a23fe9 to your computer and use it in GitHub Desktop.
Save dfpalomar/a82c0a4785635d026f80143da9a23fe9 to your computer and use it in GitHub Desktop.
package acme;
import com.yoti.mobile.android.connections.p2p.internal.exception.CryptoException;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* Utility class to perform both symmetric and asymmetric operations.
*/
public class CryptographyUtil {
private static final String RSA_ALGORITHM = "RSA";
private static final String AES_ALGORITHM = "AES";
private static final String RNG_ALGORITHM = "SHA1PRNG";
private static final String ASYMMETRIC_TRANSFORMATION = "RSA/NONE/PKCS1Padding";
private static final String SYMMETRIC_TRANSFORMATION = "AES/CBC/PKCS5PADDING";
private static final int ASYMMETRIC_KEY_LENGTH = 2048;
private static final int SYMMETRIC_KEY_LENGTH = 256;
public KeyPair generateKeyPair() throws GeneralSecurityException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(RSA_ALGORITHM);
keyGen.initialize(ASYMMETRIC_KEY_LENGTH, new SecureRandom());
return keyGen.generateKeyPair();
}
public byte[] generateAESKey() throws CryptoException {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
keyGenerator.init(SYMMETRIC_KEY_LENGTH, new SecureRandom());
Key key = keyGenerator.generateKey();
return key.getEncoded();
} catch (NoSuchAlgorithmException e) {
throw new CryptoException(e);
}
}
public byte[] generateIV() throws CryptoException {
try {
Cipher cipher = Cipher.getInstance(SYMMETRIC_TRANSFORMATION);
byte[] iv = new byte[cipher.getBlockSize()];
SecureRandom.getInstance(RNG_ALGORITHM).nextBytes(iv);
return new IvParameterSpec(iv).getIV();
} catch (GeneralSecurityException e) {
throw new CryptoException(e);
}
}
public byte[] asymmetricEncrypt(byte[] publicKey, byte[] inputData) throws GeneralSecurityException {
PublicKey key = KeyFactory.getInstance(RSA_ALGORITHM).generatePublic(
new X509EncodedKeySpec(publicKey)
);
return asymmetricCryptoOperation(Cipher.PUBLIC_KEY, key, inputData);
}
public byte[] asymmetricDecrypt(byte[] privateKey, byte[] inputData) throws GeneralSecurityException {
PrivateKey key = KeyFactory.getInstance(RSA_ALGORITHM).generatePrivate(
new PKCS8EncodedKeySpec(privateKey)
);
return asymmetricCryptoOperation(Cipher.PRIVATE_KEY, key, inputData);
}
private byte[] asymmetricCryptoOperation(int mode, Key key, byte[] data) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(ASYMMETRIC_TRANSFORMATION);
cipher.init(mode, key);
return cipher.doFinal(data);
}
public byte[] aesEncrypt(byte[] key, byte[] iv, byte[] data) throws GeneralSecurityException {
return symmetricCryptoOperation(Cipher.ENCRYPT_MODE, key, iv, data);
}
public byte[] aesDecrypt(byte[] key, byte[] iv, byte[] data) throws GeneralSecurityException {
return symmetricCryptoOperation(Cipher.DECRYPT_MODE, key, iv, data);
}
private byte[] symmetricCryptoOperation(int mode, byte[] key, byte[] iv, byte[] data) throws GeneralSecurityException {
SecretKeySpec keySpec = new SecretKeySpec(key, AES_ALGORITHM);
Cipher cipher = Cipher.getInstance(SYMMETRIC_TRANSFORMATION);
cipher.init(mode, keySpec, new IvParameterSpec(iv));
return cipher.doFinal(data);
}
}
@dfpalomar
Copy link
Author

Test

package acme;

import static org.junit.Assert.assertArrayEquals;

import java.security.KeyPair;
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;

public class CryptographyUtilTest {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    @Test
    public void testAsymmetricCryptoOperations() throws Exception {

        CryptographyUtil cryptographyUtil = new CryptographyUtil();

        KeyPair keyPair = cryptographyUtil.generateKeyPair();

        byte[] originalText = "Hello World!".getBytes();

        byte[] encryptedText = cryptographyUtil.asymmetricEncrypt(
            keyPair.getPublic().getEncoded(),
            originalText
        );
        byte[] decryptedText = cryptographyUtil.asymmetricDecrypt(
            keyPair.getPrivate().getEncoded(),
            encryptedText
        );

        assertArrayEquals(originalText, decryptedText);
    }

    @Test
    public void testSymmetricCryptoOperations() throws Exception {
        CryptographyUtil cryptographyUtil = new CryptographyUtil();

        byte[] key = cryptographyUtil.generateAESKey();
        byte[] iv = cryptographyUtil.generateIV();

        byte[] originalText = "Hello World!".getBytes();

        byte[] encryptedText = cryptographyUtil.aesEncrypt(key, iv, originalText);
        byte[] decryptedText = cryptographyUtil.aesDecrypt(key, iv, encryptedText);

        assertArrayEquals(originalText, decryptedText);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment