one.credify.crypto.Encryption Maven / Gradle / Ivy
package one.credify.crypto;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.security.*;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* RSA 4096 bit encryption
*/
public class Encryption {
private PublicKey publicKey;
private PrivateKey privateKey;
private static int KEY_SIZE = 3072;
public Encryption() {
Security.addProvider(new BouncyCastleProvider());
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public PublicKey getPublicKey() {
return publicKey;
}
public byte[] getPublicKeyEncoded() {
return publicKey.getEncoded();
}
public byte[] getPrivateKeyEncoded() {
return privateKey.getEncoded();
}
public String getPublicKeyString() {
String data = Base64.getEncoder().encodeToString(this.getPublicKeyEncoded());
return Utils.BEGIN_PUBLIC_KEY + data.replaceAll("(.{64})", "$1\n") + Utils.END_PUBLIC_KEY;
}
public String getPublicKeyInBase64Url() {
return Base64.getUrlEncoder().withoutPadding().encodeToString(this.getPublicKeyEncoded());
}
public String getPrivateKeyString() {
String data = Base64.getEncoder().encodeToString(this.getPrivateKeyEncoded());
return Utils.BEGIN_PRIVATE_KEY + data.replaceAll("(.{64})", "$1\n") + Utils.END_PRIVATE_KEY;
}
public void generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC");
keyGen.initialize(KEY_SIZE);
KeyPair keyPair = keyGen.generateKeyPair();
this.privateKey = keyPair.getPrivate();
this.publicKey = keyPair.getPublic();
}
public void importPrivateKey(String pem) throws InvalidKeySpecException, NoSuchAlgorithmException {
String privateKeyPEM = pem;
privateKeyPEM = privateKeyPEM.replace(Utils.BEGIN_PRIVATE_KEY, "");
privateKeyPEM = privateKeyPEM.replace(Utils.END_PRIVATE_KEY, "");
privateKeyPEM = privateKeyPEM.replace("\n", "");
byte[] encoded = Base64.getDecoder().decode(privateKeyPEM);
PKCS8EncodedKeySpec key = new PKCS8EncodedKeySpec(encoded);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
this.privateKey = keyFactory.generatePrivate(key);
RSAPrivateCrtKey rsaPrivateCrtKey = (RSAPrivateCrtKey) this.privateKey;
RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(rsaPrivateCrtKey.getModulus(), rsaPrivateCrtKey.getPublicExponent());
this.publicKey = keyFactory.generatePublic(publicKeySpec);
}
public void importKey(String pem, String password) throws IOException, PKCSException, OperatorCreationException, NoSuchAlgorithmException, InvalidKeySpecException {
if (!pem.startsWith(Utils.BEGIN_ENCRYPTED_PRIVATE_KEY)) {
pem = Utils.BEGIN_ENCRYPTED_PRIVATE_KEY + pem + Utils.END_ENCRYPTED_PRIVATE_KEY;
}
PEMParser pemParser = new PEMParser(new StringReader(pem));
Object o = pemParser.readObject();
KeyPair kp;
if (o instanceof PKCS8EncryptedPrivateKeyInfo) {
// Encrypted key - we will use provided password
PKCS8EncryptedPrivateKeyInfo ckp = (PKCS8EncryptedPrivateKeyInfo) o;
// uses the password to decrypt the key
InputDecryptorProvider decProv = new JceOpenSSLPKCS8DecryptorProviderBuilder()
.setProvider(BouncyCastleProvider.PROVIDER_NAME).build(password.toCharArray());
PrivateKeyInfo privateKeyInfo = ckp.decryptPrivateKeyInfo(decProv);
PKCS8EncodedKeySpec key = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
this.privateKey = keyFactory.generatePrivate(key);
RSAPrivateCrtKey rsaPrivateCrtKey = (RSAPrivateCrtKey) this.privateKey;
RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(rsaPrivateCrtKey.getModulus(), rsaPrivateCrtKey.getPublicExponent());
this.publicKey = keyFactory.generatePublic(publicKeySpec);
} else {
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
// Unencrypted key - no password needed
PEMKeyPair ukp = (PEMKeyPair) o;
kp = converter.getKeyPair(ukp);
this.privateKey = kp.getPrivate();
this.publicKey = kp.getPublic();
}
}
public void importPublicKey(String pem) throws InvalidKeySpecException, NoSuchAlgorithmException {
String publicKeyPEM = pem;
publicKeyPEM = publicKeyPEM.replace(Utils.BEGIN_PUBLIC_KEY, "");
publicKeyPEM = publicKeyPEM.replace(Utils.END_PUBLIC_KEY, "");
publicKeyPEM = publicKeyPEM.replace("\n", "");
byte[] encoded = Base64.getDecoder().decode(publicKeyPEM);
importPublicKey(encoded);
}
public void importPublicKeyInBase64Url(String pem) throws InvalidKeySpecException, NoSuchAlgorithmException {
String publicKeyPEM = pem;
publicKeyPEM = publicKeyPEM.replace(Utils.BEGIN_PUBLIC_KEY, "");
publicKeyPEM = publicKeyPEM.replace(Utils.END_PUBLIC_KEY, "");
publicKeyPEM = publicKeyPEM.replace("\n", "");
byte[] encoded = Base64.getUrlDecoder().decode(publicKeyPEM);
importPublicKey(encoded);
}
private void importPublicKey(byte[] encoded) throws NoSuchAlgorithmException, InvalidKeySpecException {
X509EncodedKeySpec key = new X509EncodedKeySpec(encoded);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
this.publicKey = keyFactory.generatePublic(key);
}
public byte[] encrypt(byte[] data) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, BadPaddingException, IllegalBlockSizeException, IOException {
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding", new BouncyCastleProvider());
OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);
cipher.init(Cipher.ENCRYPT_MODE, this.publicKey, oaepParams);
int blockSize = cipher.getBlockSize();
int dataLength = data.length;
int start = 0;
int end = 0;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
while (end < dataLength) {
end = end + blockSize;
if (end > dataLength) {
end = dataLength;
}
byte[] encryptedSlide = cipher.doFinal(data, start, (end - start));
stream.write(encryptedSlide);
start = end;
}
return stream.toByteArray();
}
public String encryptString(String message) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, IOException {
byte[] data = this.encrypt(message.getBytes());
return Base64.getUrlEncoder().withoutPadding().encodeToString(data);
}
public String decrypt(byte[] data) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, IOException {
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding", new BouncyCastleProvider());
OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);
cipher.init(Cipher.DECRYPT_MODE, this.privateKey, oaepParams);
int blockSize = cipher.getBlockSize();
int dataLength = data.length;
int start = 0;
int end = 0;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
while (end < dataLength) {
end = end + blockSize;
if (end > dataLength) {
end = dataLength;
}
byte[] decryptedBlockData = cipher.doFinal(data, start, (end - start));
stream.write(decryptedBlockData);
start = end;
}
return stream.toString();
}
public String decryptString(String message) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IOException {
byte[] data = Base64.getUrlDecoder().decode(message);
return this.decrypt(data);
}
public Object decryptObject(Object message) throws InvalidAlgorithmParameterException, IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, InvalidKeyException, IOException {
if (message == null) {
return null;
}
if (message instanceof Map) {
Map objectMap = (Map) message;
Map result = new HashMap<>();
for (Map.Entry entry : objectMap.entrySet()) {
Object decryptedObj = decryptObject(entry.getValue());
result.put(entry.getKey(), decryptedObj);
}
return result;
}
if (message instanceof String) {
if (((String) message).length() == 0) {
return message;
}
return decryptString((String) message);
}
return message;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy