This question already has answers here:
Encrypting and Decrypting String using a Java equilavent of the C# CryptoStream
(7 answers)
Closed 9 years ago.
I need a encrypt/decrypt algorithm for database keys at a java Aplication.
I have to use a algoritmh implement previously using c#, but some classes it use, dont have a java equivalent.
This is the c# code:
public static string Encryptor(string text)
{
SymmetricAlgorithm saEnc;
byte[] dataorg = Encoding.Default.GetBytes(text);
saEnc = SymmetricAlgorithm.Create("RC2");
ICryptoTransform ct = saEnc.CreateEncryptor(Key, Vector);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
cs.Write(dataorg, 0, dataorg.Length);
cs.FlushFinalBlock();
string retorno = Convert.ToBase64String(ms.ToArray());
ms.Close();
saEnc.Clear();
cs.Clear();
cs.Close();
ms = null;
saEnc = null;
cs = null;
return retorno;
}
/**********************************************************************************
DESCRIPCIÓN: Desencripta un texto
PARÁMETROS:
Entrada:
text Texto a desencriptar
Salida:
Texto desencriptado
**********************************************************************************/
public static string Decryptor(string text)
{
SymmetricAlgorithm saDEnc = SymmetricAlgorithm.Create("RC2");
byte[] textoEncriptado = Convert.FromBase64String(text);
MemoryStream ms = new MemoryStream(textoEncriptado);
ICryptoTransform cto = saDEnc.CreateDecryptor(Key, Vector);
MemoryStream mso = new MemoryStream();
CryptoStream cso = new CryptoStream(mso, cto, CryptoStreamMode.Write);
cso.Write(ms.ToArray(), 0, ms.ToArray().Length);
cso.FlushFinalBlock();
string retorno = Encoding.Default.GetString(mso.ToArray());
saDEnc.Clear();
ms.Close();
mso.Close();
cso.Clear();
cso.Close();
saDEnc = null;
ms = null;
mso = null;
cso = null;
return retorno;
}
Some help to create a equivalent code at java? or other alternative?
THanks!
This should do it for you.
public static String encrypt(byte[] key, byte[] iv, String unencrypted) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException{
RC2ParameterSpec ivSpec = new RC2ParameterSpec(key.length*8, iv);
Cipher cipher = Cipher.getInstance("RC2/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "RC2"), ivSpec);
byte[] encrypted = cipher.doFinal(unencrypted.getBytes());
return DatatypeConverter.printBase64Binary(encrypted);
}
public static String decrypt(byte[] key, byte[] iv, String encrypted) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException{
RC2ParameterSpec ivSpec = new RC2ParameterSpec(key.length*8, iv);
Cipher cipher = Cipher.getInstance("RC2/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "RC2"), ivSpec);
byte[] decrypted = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted));
return new String(decrypted);
}
Using the same Key and IV (Vector in your code), these methods will produce input/output compatible with the code you've listed.
Related
I am trying to implement AEPS API but unable to encrypt aadhar number in php. In developer guide they provided method to encrypt using JAVA and i am using php.
Given JAVA code is as follows.
public static String calculateRSA( String salt ) throws InvalidKeyException, Exception {
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, getPublicKey());
byte[] secretMessageBytes = salt.getBytes("UTF-8");
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
String encodedMessage = Base64.encodeBase64String(encryptedMessageBytes);
return encodedMessage;
}
public static PublicKey getPublicKey() throws Exception {
String rawPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaFyrzeDhMaFLx+LZUNOOO14Pj9aPfr+1WOanDgDHxo9NekENYcWUftM9Y17ul2pXr3bqw0GCh4uxNoTQ5cTH4buI42LI8ibMaf7Kppq9MzdzI9/7pOffgdSn+P8J64CJAk3VrVswVgfy8lABt7fL8R6XReI9x8ewwKHhCRTwBgQIDAQAB";
byte[] keyBytes = Base64.decodeBase64(rawPublicKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);// generatePrivate(spec);
}
I tried
$publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaFyrzeDhMaFLx+LZUNOOO14Pj9aPfr+1WOanDgDHxo9NekENYcWUftM9Y17ul2pXr3bqw0GCh4uxNoTQ5cTH4buI42LI8ibMaf7Kppq9MzdzI9/7pOffgdSn+P8J64CJAk3VrVswVgfy8lABt7fL8R6XReI9x8ewwKHhCRTwBgQIDAQAB';
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey($publicKey); // public key
$plaintext = '828409353766';
//$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP);
$encrypted = $rsa->encrypt($plaintext);
$encrypted = base64_encode($encrypted);
I'm trying to rewrite the following implementation of AES-256-GCM encryption from NodeJS to Java.
Packet description
Im getting a different output, specifically the auth tag part. From the looks of it, the Java libs dont have any methods to fetch the auth tag, and my attempt to substring it from the output fails. Also, I'm not actually sure that the first AES encryption with the public key (generating a random buffer for GCM) works the same as the NodeJS counterpart.
Can anyone point me in the right direction?
NodeJS:
public encryptPassword(password: string, encryptionKey: string, encryptionKeyId: string): { time: string, encrypted: string } {
const randKey = crypto.randomBytes(32);
const iv = crypto.randomBytes(12);
const rsaEncrypted = crypto.publicEncrypt({
key: Buffer.from(encryptionKey, 'base64').toString(),
// #ts-ignore
padding: crypto.constants.RSA_PKCS1_PADDING,
}, randKey);
const cipher = crypto.createCipheriv('aes-256-gcm', randKey, iv);
const time = Math.floor(Date.now() / 1000).toString();
cipher.setAAD(Buffer.from(time));
const aesEncrypted = Buffer.concat([cipher.update(password, 'utf8'), cipher.final()]);
const sizeBuffer = Buffer.alloc(2, 0);
sizeBuffer.writeInt16LE(rsaEncrypted.byteLength, 0);
const authTag = cipher.getAuthTag();
return {
time,
encrypted: Buffer.concat([
Buffer.from([1, encryptionKeyId]),
iv,
sizeBuffer,
rsaEncrypted, authTag, aesEncrypted])
.toString('base64'),
};
}
Java:
private static Pair<Long, String> encryptPaswword(String password, String encryptionPubKey, String encryptionKeyId) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidCipherTextException, InvalidAlgorithmParameterException {
byte[] passwordAsByte = password.getBytes();
String decoededPubKey = new String(Base64.decode(encryptionPubKey, Base64.NO_WRAP), StandardCharsets.UTF_8);
decoededPubKey = decoededPubKey.replace("-----BEGIN PUBLIC KEY-----", "");
decoededPubKey = decoededPubKey.replace("-----END PUBLIC KEY-----", "");
SecureRandom random = new SecureRandom();
byte[] randKey = new byte[32];
random.nextBytes(randKey);
byte[] iv = new byte[12];
random.nextBytes(iv);
long date = new Date().getTime() / 1000;
ByteBuffer header = ByteBuffer.allocate(2);
header.put(Integer.valueOf(1).byteValue());
header.put(Integer.valueOf(Integer.parseInt(encryptionKeyId)).byteValue());
ByteBuffer timeAAD = ByteBuffer.allocate(10);
timeAAD.put(String.valueOf(date).getBytes());
X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(Base64.decode(decoededPubKey, Base64.NO_WRAP));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(publicSpec);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] rsaEncrypted = rsaCipher.doFinal(randKey);
ByteBuffer sizeBuff = ByteBuffer.allocate(2);
sizeBuff.put(Integer.valueOf(rsaEncrypted.length).byteValue());
final Cipher gcmCipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(16 * Byte.SIZE, iv);
gcmCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(randKey, "AES"), parameterSpec);
gcmCipher.updateAAD(timeAAD);
byte[] gcmText= gcmCipher.doFinal(passwordAsByte);
ByteBuffer result = ByteBuffer.allocate(2+12+2+256+gcmText.length);
result.put(header);
result.put(iv);
result.put(sizeBuff);
result.put(rsaEncrypted);
result.put(Arrays.copyOfRange(gcmText, gcmText.length - (16 / Byte.SIZE), gcmText.length));
result.put(Arrays.copyOfRange(gcmText, 0, gcmText.length - (16 / Byte.SIZE)));
return new Pair(new Long(date), Base64.encodeToString(result.array(), Base64.NO_WRAP));
This question already has answers here:
IllegalBlockSizeException when trying to encrypt and decrypt a string with AES
(4 answers)
Closed 6 years ago.
I am trying to encode the passphase into a properties file so that I don't have to type in the passphase to make an SSH connection. But I am facing the following error :
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at com.test.ssh.SSH_Public_Private.deCryptPwd(SSH_Public_Private.java:191)
at com.test.ssh.SSH_Public_Private.checkHostName(SSH_Public_Private.java:227)
at com.test.ssh.SSH_Public_Private.checkHostName(SSH_Public_Private.java:223)
at com.test.ssh.SSH_Public_Private.connectToSSH(SSH_Public_Private.java:64)
at com.test.ssh.SSH_Public_Private.main(SSH_Public_Private.java:124)
My code is as follows:
private String checkHostName(String hostUserName) throws IOException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
String deCrypted = null;
FileInputStream is = new FileInputStream(new File("C:\\test\\SSH\\PrivateKey\\keystore.properties"));
Properties properties = new Properties();
properties.load(is);
ssh_Public_Private = new SSH_Public_Private();
boolean isHostNameExist = false;
if (properties.getProperty(hostUserName) == null) {
OutputStream outputStream = new FileOutputStream(
"C:\\test\\SSH\\PrivateKey\\keystore.properties");
String passPhraseStored = new String(enCryptPwd());
properties.setProperty(hostUserName,passPhraseStored );
properties.store(outputStream, null);
outputStream.close();
is.close();
return checkHostName(hostUserName);
}else{
System.out.println(properties.getProperty(hostUserName));
String passPhrase = properties.getProperty(hostUserName);
deCrypted = deCryptPwd(passPhrase); //isHostNameExist = true;
}
return deCrypted;
}
My encryption and decryption piece of code is as follow :
private static String enCryptPwd() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
String decrypted = null;
byte[] encrypted = null;
try {
String text = "";
Scanner sc = new Scanner(System.in);
System.out.println("Enter your passphrase : " );
text = sc.next();
String key = "Bar12345Bar12345"; // 128 bit key
//String key = "AesSEcREtkeyABCD";
// Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
System.out.println(aesKey.getFormat());
Cipher cipher = Cipher.getInstance("AES");
// encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
encrypted = cipher.doFinal(text.getBytes("UTF-8"));
System.err.println(new String(encrypted));
System.err.println(encrypted.length);
} catch (Exception e) {
e.printStackTrace();
}
return new String(encrypted);
}
private static String deCryptPwd(String encrypted) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
String originalString = "";
try {
String key = "Bar12345Bar12345"; // 128 bit key
//String key = "AesSEcREtkeyABCD";
// Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES");
// decrypt the text
cipher.init(Cipher.DECRYPT_MODE, aesKey);
byte[] encryptBytes = new byte[encrypted.length()];
encryptBytes = encrypted.getBytes();
byte[] decrypted = cipher.doFinal(encryptBytes);
originalString = new String(decrypted, "UTF-8");
System.out.println(originalString);
System.err.println(decrypted);
} catch (Exception e) {
e.printStackTrace();
}
return originalString;
}
I have been trying to read up and I have tried many other ways by including no padding Algorithms as well. My code writes the output into a property file as :
abced=Y\u201Eh\uFFFD\u00EC-:\u00F9\u00F8mC\u0160\u0002\u00F3#\u00DE
My console outputs are :
Enter your passphrase :
abc!##
After encryption >> Y„h?ì-:ùømCŠó#Þ
16
Read from property file >> Y„h?ì-:ùømCŠó#Þ
Generate key using KeyGenerator
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128, new SecureRandom());
SecretKeySpec aesKey = new SecretKeySpec(kg.generateKey().getEncoded(), "AES");
Use AES/CBC/PKCS5Padding to get cipher instance.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
This should work.
I have the following code,
public static String encrypt(String plainText, String key){
try{
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decode(key, Base64.DEFAULT)));
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeToString(cipher.doFinal(plainText.getBytes("UTF-8")),Base64.DEFAULT);
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
I want to convert this to C#. I have tried CryptUtils but it doesn't work https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/CryptUtils.cs
Sample key,
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ9AMIIBCgKCAQEAoqB1N9kugk4UKYnbh0fcg3qYyYKP0m4B
MjWd05ReeAdj+7JRYDEKO6xthDdVSdRO1/2V+YtY8DnXWnxRaICwu8235s3imZCyqgYnomPWdY+F
K540oTz/zug+9wbrlzt/WQFUU4lPlQbzm/Gjw8XfaCozT0e3bnWQcD7rORCOyuJgwSGgREjTv1ss
pgEaKTMknii9vpGZLeAXwoeIYROhuT4IoIkPDhtY0/UZiCi6v7Ja2dmy53VlWIkcm3rcnSJdvpXr
OgiHvaNABHmeymNycNqd6WUaysBRheluQ86nq/2nZPW0gcvmYt5zbMMYX3yY/n2WtAKeNQBAEW1q
b0s6MwIDAQAB
Possible encryped value,
Y3VTjghDnTrCeG8C/RklKsJ3Y0Mt89sSGGin28E4iQPQvKqeZBws7rBQEZaRamDWftxCkEYZs4Qh
V2l4IVlrawdtRmQlcQh8McrpqP/97Gz8pEDEYnqA7kqBTqZw0Z5o0WsshGSwiAQ9wNSym4xHejkq
zrKxWP8XCMkcT0NlKlRMoqKKICFKZbqWeSQkQM5y9OEcmB6inNNkJCoM1Ip48+cK3cOE6dqXNVrl
sSTZ8WQKwoB3dJmcYqexR3kAvBYdX6ZxEF+2+6b9h8+tc5G7Y5R2eqycyUossdkCcI3fNVhyc72P
axCjZFWZUgfDGCxg1WNhStrH9L8c59P35JKKug==
Since i don't have the private key, i can't decrypt, but at least this produces the right lengthed values.
So try this (you need bouncycastle for reading pem):
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
var keyBytes =
Convert.FromBase64String(
"MIIBI...."); // your key here
AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(keyBytes);
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter;
RSAParameters rsaParameters = new RSAParameters();
rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);
byte[] plaintext = Encoding.UTF8.GetBytes("amount=1¤cy=AED");
byte[] ciphertext = rsa.Encrypt(plaintext, false);
string cipherresult = Convert.ToBase64String(ciphertext);
I have a simple code here, the code uses the sun.misc.BASE64Encoder and sun.misc.BASE64Decoder, which are not available in Eclipse Java 7.0 , I wanted to make the code such that it uses the Apache commons base 64 and still do exactly the same thing,
The variables
private static final String ALGORITHM = "AES";
private static final byte[] keyValue = "2H5a1r5i6s3h8C1h".getBytes();
Original Code
public static String AESencrypt(String valueToEnc) throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
String encryptedValue = new BASE64Encoder().encode(encValue);
return encryptedValue;
}
public static String AESdecrypt(String encryptedValue) throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
Trying to modify to apache commons code
public static String AESencrypt(String valueToEnc) throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
String encryptedValue = new Base64().encodeBase64(encValue).toString();
return encryptedValue;
}
public static String AESdecrypt(String encryptedValue) throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new Base64().decodeBase64(encryptedValue);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
The original code works fine, the new code throws the following exception,
Exception in thread "main" javax.crypto.IllegalBlockSizeException:
Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at
com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087) at
trial2.encrypt.AESdecrypt(encrypt.java:28) at
trial2.encrypt.main(encrypt.java:37)
Java Result: 1
How can I solve this problem without altering the initial code too much, a few lines here and there are OK. Is it possible to completely eliminate the Base64encoding step and make it work with only the ciphers like this:
public static String AESencrypt(String valueToEnc) throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
return encValue.toString();
}
public static String AESdecrypt(String encryptedValue) throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decValue = c.doFinal(encryptedValue.getBytes());
String decryptedValue = new String(decValue);
return decryptedValue;
}
The above code has similar exception like the second code:
Exception in thread "main" javax.crypto.IllegalBlockSizeException:
Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at
com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087) at
trial2.encrypt.AESdecrypt(encrypt.java:26) at
trial2.encrypt.main(encrypt.java:35) Java Result: 1
Please help and TYVM
The error is in your encrypt method. The following code is wrong:
byte[] encValue = c.doFinal(valueToEnc.getBytes());
String encryptedValue = new Base64().encodeBase64(encValue).toString();
You are calling toString() on a byte array, which won't do what you want! Instead, try:
byte[] encValue = c.doFinal(valueToEnc.getBytes());
String encryptedValue = Base64.encodeBase64String(encValue);
This should then work correctly.