I want to translate CryptoJS code into java code .This is the javascript code:
CryptoJS.AES.encrypt('hello',CryptoJS.enc.Utf8.parse(CryptoJS.MD5("http://stackoverflow.com")), {iv: CryptoJS.enc.Utf8.parse("1234567812345678")})
Above the code result invoke to string is 'QtzDsbCgmA9+XBVEsEm70w=='
Then I get the key value by CryptoJS.MD5("http://stackoverflow.com").toString() method(key = 57f4dad48e7a4f7cd171c654226feb5a)
This is the java code:
try {
String content = "hello";
String key = "57f4dad48e7a4f7cd171c654226feb5a";
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(key.getBytes("utf-8")));
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key1 = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key1,new IvParameterSpec("1234567812345678".getBytes("UTF-8")));
byte[] result = cipher.doFinal(byteContent);
System.out.println(new String(result).equals("QtzDsbCgmA9+XBVEsEm70w=="));
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
but the output result is false.How to fix the java code to change the result to true.
According to #Luka Park advice,I have solve to my question.This is my solution:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] raw = sKey.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
return new BASE64Encoder().encode(encrypted);
Related
I am getting this error when I am decrypting a file
I am using PBKDF2 to convert a passphrase to a key and then using it. The encryption is working good but when I am trying to decrypt the same file it is giving the below error. The decrypted file gives a correct data except for the last few lines(probably the padding area). I have debugged it by outputting the IV and key while encrypting and decrypting and they both are the same but the error still exists.
public class FileEncryptorSkeleton{
private static final String progName = "FileEncryptor";
private static final int bufSize = 128;
/**
* #param args
*/
public static void main(String[] args) throws UnsupportedEncodingException {
BufferedInputStream in = null; // A buffered input stream to read from
BufferedOutputStream out = null; // And a buffered output stream to write to
SecretKeyFactory kf = null; // Something to create a key for us
KeySpec ks = null; // This is how we specify what kind of key we want it to generate
byte[] salt = new byte[20]; // Some salt for use with PBKDF2, only not very salty
SecretKey key = null; // The key that it generates
Cipher cipher = null; // The cipher that will do the real work
SecretKeySpec keyspec = null; // How we pass the key to the Cipher
int bytesRead = 0; // Number of bytes read into the input file buffer
byte[] iv = new byte[16];
// First, check the user has provided all the required arguments, and if they haven't, tell them then exit
if(args.length != 4) {
printUsageMessage(); System.exit(1);
}
// Open the input file
try {
in = new BufferedInputStream(new FileInputStream(args[1]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open input file: " + args[1], null);
System.exit(1);
}
// And then the output file
try {
out = new BufferedOutputStream(new FileOutputStream(args[2]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open output file: " + args[2], e);
System.exit(1);
}
try {
kf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(FileEncryptorSkeleton.class.getName()).log(Level.SEVERE, null, ex);
}
// Set up a KeySpec for password-based key generation of a 128-bit key
ks = new PBEKeySpec(args[3].toCharArray(), salt, 1000, 128);
// Now run the passphrase through PBKDF2 to get the key
try {
key = kf.generateSecret(ks);
}catch(InvalidKeySpecException e){
System.exit(1);
}
// Get the byte encoded key value as a byte array
byte[] aeskey = key.getEncoded();
// Now generate a Cipher object for AES encryption in ECBC mode with PKCS #5 padding
// Use ECB for the first task, then switch to CBC for versions 2 and 3
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
printErrorMessage("No Such Algorithm Exception when creating main cipher", e);
System.exit(2);
} catch (NoSuchPaddingException e) {
printErrorMessage("No Such Padding Exception when creating main cipher",e);
System.exit(2);
}
// Set a variable to indicate whether we're in encrypt or decrypt mode, based upon args[0]
int cipherMode = -1;
char mode = Character.toLowerCase(args[0].charAt(0));
switch (mode) {
case 'e' : cipherMode = Cipher.ENCRYPT_MODE; break;
case 'd' : cipherMode = Cipher.DECRYPT_MODE; break;
default: printUsageMessage(); System.exit(1);
}
// Set up a secret key specification, based on the 16-byte (128-bit) AES key array previously generated
keyspec = new SecretKeySpec(aeskey, "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv);
// Now initialize the cipher in the right mode, with the keyspec and the ivspec
try {
cipher.init(cipherMode, keyspec,ivspec);
} catch (InvalidKeyException e) {
printErrorMessage("Invalid Key Spec",e); System.exit(2);
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(FileEncryptorSkeleton.class.getName()).log(Level.SEVERE, null, ex);
}
// Set up some input and output byte array buffers
byte[] inputBuffer = new byte[bufSize];
byte[] outputBuffer = null;
// "Prime the pump" - we've got to read something before we can encrypt it
// and not encrypt anything if we read nothing.
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e) {
printErrorMessage("Error reading input file " + args[1],e); System.exit(1);
}
// As long as we've read something, loop around encrypting, writing and reading
// bytesRead will be zero if nothing was read, or -1 on EOF - treat them both the same
while (bytesRead > 0) {
// Now encrypt this block
outputBuffer = cipher.update(inputBuffer.toString().getBytes("UTF-8"));
// Write the generated block to file
try {
out.write(outputBuffer);
} catch (IOException e) {
printErrorMessage("Error writing to output file " + args[2],e); System.exit(1);
}
// And read in the next block of the file
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e) {
printErrorMessage("Error reading input file " + args[1],e); System.exit(1);
}
}
try {
// Now do the final processing
outputBuffer =cipher.doFinal(inputBuffer.toString().getBytes("UTF-8"));
cipher.init(cipherMode, keyspec,ivspec);
System.out.println(ivspec+" "+cipherMode+" "+keyspec);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(FileEncryptorSkeleton.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(FileEncryptorSkeleton.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(FileEncryptorSkeleton.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(FileEncryptorSkeleton.class.getName()).log(Level.SEVERE, null, ex);
}
// Write the final block of output
try {
out.write(outputBuffer);
} catch (IOException e) {
printErrorMessage("Error on final write to output file " + args[2],e); System.exit(1);
}
// Close the output files
try {
in.close();
out.close();
} catch (IOException e) {
printErrorMessage("Error closing file", e);
}
// If we were continuing beyond this point, we should really overwrite key material, drop KeySpecs, etc.
}
/**
* Print an error message on , optionally picking up additional detail from
* a passed exception
* #param errMsg
* #param e
*/
private static void printErrorMessage(String errMsg, Exception e) {
System.err.println(errMsg);
if (e != null)
System.err.println(e.getMessage());
}
/**
* Print a usage message
*/
private static void printUsageMessage() {
System.out.println(progName + " $Revision: 1.1 $: Usage: " + progName + " E/D infile outfile passphrase");
}
}
Oct 18, 2019 11:27:46 PM FileEncryptorSkeleton main
SEVERE: null
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at FileEncryptorSkeleton.main(FileEncryptorSkeleton.java:174)
Both the Cipher#update- and Cipher#doFinal-method use inputBuffer.toString(), which only contains the name of the object's class and the hashcode and not the actual data in the buffer.
It would be correct to read the first bytesRead bytes from the inputBuffer-byte[] (which were previously read from the in-BufferedInputStream) and process them (Cipher#update):
outputBuffer = cipher.update(inputBuffer, 0, bytesRead);
The loop containing the cipher#update-call is only left when no byte has been read to the inputBuffer-byte[], so that for the final processing applies (Cipher#doFinal):
outputBuffer = cipher.doFinal();
In addition, the second cipher#init-call immediately after the cipher#doFinal-call is unnecessary (Cipher#init).
Decryption logic is missing something can you please assist.
Output is not completely decrypted.
Java Encryption Logic:
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException {
try {
String in ="This is a text message";
byte[] input = in.toString().getBytes("utf-8");
String ENCRYPTION_KEY = "RW50ZXIgS2V5IEhlcmU=";
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] thedigest = md.digest(ENCRYPTION_KEY.getBytes("UTF-8"));
// SecretKeySpec skc = new SecretKeySpec(thedigest, "AES/ECB/PKCS5Padding");
SecretKeySpec skc = new SecretKeySpec(thedigest, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skc);
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
// String query = Base64.encodeToString(cipherText, Base64.DEFAULT);
String query = new String(java.util.Base64.getEncoder().encode(cipherText));
System.out.println("query " + query);
// String query = new String(encode(cipherText), StandardCharsets.ISO_8859_1);
} catch(UnsupportedEncodingException e) { // TODO Auto-generated catch block
e.printStackTrace();
}
}
Nodejs Decryption Logic:
let crypto = require('crypto');
var decipher = crypto.createDecipher('aes-256-ecb', "RW50ZXIgS2V5IEhlcmU=");
decipher.setAutoPadding(false);
console.log(decipher.update("EncyptedText", 'base64', 'utf8') + decipher.final('utf8'));
I am retrieving a text password as input from a file and applying AES encryption over that and later on, decrypting that.
When I did it for the first time, every 4 out of 5 times it was running correctly (encryption decryption successful) but 1 time, it was throwing BadPaddingException. Following is what I wrote :
//ABCD is class name
public static void enc(String fileName, String pwd) {
try {
Properties prop = new Properties();
InputStream input = ABCD.class.getClassLoader().getResourceAsStream(fileName);
prop.load(input);
input.close();
URL url = ABCD.class.getClassLoader().getResource(fileName);
FileOutputStream outputStream = new FileOutputStream(url.getPath());
KeyGenerator key = KeyGenerator.getInstance("AES");
key.init(128);
SecretKey aesKey = key.generateKey();
String newkey = new String(Base64.encode(aesKey.getEncoded()).getBytes("UTF-8"));
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] clear = pwd.getBytes("UTF-8");
byte[] cipher = aesCipher.doFinal(clear);
String encPwd = new String(cipher);
prop.setProperty("password", encPwd);
prop.setProperty("secKey", newkey);
prop.store(outputStream, null);
outputStream.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static String dec(Properties prop, String fileName) {
String decPwd = ABCD.map.get(fileName);
try {
String newkey = prop.getProperty("secKey");
StringBuilder pwd;
byte[] newkeybuff = Base64.decode(newkey.getBytes("UTF-8"));
SecretKey key = new SecretKeySpec(newkeyuff, "AES");
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.DECRYPT_MODE, key);
pwd = new StringBuilder(prop.getProperty("password"));
byte[] cipher = aesCipher.doFinal(pwd.toString().getBytes());
decPwd = new String(cipher);
} catch (Exception e) {
System.out.println(e);
}
ABCD.map.put(fileName, decPwd);
return decPwd;
}
I needed to fix this. Somewhere, I read that BadPaddingExcpetion occurs since of the operations done with String, in place of where actually byte should be used. Hence, I changed my code to the following :
public static void enc(String fileName, String pwd) {
try {
Properties prop = new Properties();
InputStream input = ABCD.class.getClassLoader().getResourceAsStream(fileName);
prop.load(input);
input.close();
URL url = ABCD.class.getClassLoader().getResource(fileName);
FileOutputStream outputStream = new FileOutputStream(url.getPath());
KeyGenerator key = KeyGenerator.getInstance("AES");
key.init(128);
SecretKey aesKey = key.generateKey();
byte[] newkey=(Base64.encode(aesKey.getEncoded())).getBytes("UTF-8");
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey,new IvParameterSpec(new byte[16]));
byte[] clear = pwd.getBytes("UTF-8");
byte[] cipher = aesCipher.doFinal(clear);
prop.setProperty("password", Arrays.toString(cipher));
prop.setProperty("secKey", Arrays.toString(newkey));
prop.store(outputStream, null);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static String dec(Properties prop, String fileName) {
String decPwd = ABCD.map.get(fileName);
try {
byte[] newkey=prop.getProperty("secKey").getBytes("UTF-8");
byte[] pwd;
byte[] newkeybuff = Base64.decode(newkey);
SecretKeySpec key = new SecretKeySpec(newkeybuff, "AES");
Cipher aesCipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(new byte[16]));
pwd = prop.getProperty("password").getBytes();
byte[] cipher = aesCipher.doFinal(pwd);
decPwd=new String(cipher);
System.out.println("Decrypted pwd " + decPwd);
}
catch (Exception e) {
System.out.println(e);
}
ABCD.map.put(fileName, decPwd);
return decPwd;
}
Now, I am getting InvalidKeyException. This time, I read that the size of the key should be 16 bytes. But I don't know how to apply this. Need a fix for this!
You should check your IV (Initialization Vector) which must be the same for encryption and decryption.
A padding error usually means the decryption failed.
Check that the key is a full length (16, 24 or 32 bytes), the IV is full length (16-bytes). If the key or IV is to short it will be padded with "something"and that man not be consistent, there is no standard for such padding.
getBytes("UTF-8") may return different length of bytes depending on the characters used.
Using new IvParameterSpec(new byte[16]) for the IV is incorrect, the IV should be a random bytes. A usual method of handling the IV is to create a random IV on encryption and prepend it to the encrypted data, it does not need to be secret and by prepending it will be available for decryption.
I am trying to encrypt a string using the KeyStore and used this post as reference.
KeyPairGeneratorSpec replacement with KeyGenParameterSpec.Builder equivalents - Keystore operation failed
yet, I keep getting this "bad base-64" when I decrypt the string. I am not understanding exactly how to fix this. I understand that the encrypted string contains characters that the decryptor does not know. But I don't understand the fix.
I saw some posts like those, but did not help much since there is no code on the answers.
java.lang.IllegalArgumentException: bad base-64
This is a snipped of my the test code, can someone show me how I decrpyt my string?
Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
inCipher.init(Cipher.ENCRYPT_MODE, publicKey);
Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
outCipher.init(Cipher.DECRYPT_MODE, privateKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
cipherOutputStream.write(plainText.getBytes("UTF-8"));
cipherOutputStream.close();
String ecryptedText = outputStream.toString();
Log.d(TAG, "Encrypt = " + ecryptedText);
String cipherText = ecryptedText;
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
String finalText = new String(bytes, 0, bytes.length, "UTF-8");
Log.d(TAG, "Decrypt = " + ecryptedText);
Here is a working example on how you can use Android KeyStore to Encrypt/Decrypt memory strings by using ByteArrayOutputStream and ByteArrayInputStream. Notice the provider change, for >= 6 use "AndroidKeyStoreBCWorkaround" and for older versions use "AndroidOpenSSL". Also, you have to encode the encrypted data to Base64 string using Base64.encodeToString like this:
String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
My final working example based on your code
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
"key1",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.build());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// error in android 6: InvalidKeyException: Need RSA private or public key AndroidOpenSSL
// error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround
String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround";
Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
inCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
outCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
String plainText = "This is a text";
cipherOutputStream.write(plainText.getBytes("UTF-8"));
cipherOutputStream.close();
String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
Log.d(TAG, "Encrypt = " + ecryptedText);
String cipherText = ecryptedText;
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
String finalText = new String(bytes, 0, bytes.length, "UTF-8");
Log.d(TAG, "Decrypt = " + finalText);
} catch (javax.crypto.NoSuchPaddingException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (NoSuchProviderException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (InvalidAlgorithmParameterException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (InvalidKeyException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (UnsupportedOperationException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
OUTPUTS
D/MainActivity: Encrypt = rejkfeas3HgYnZOlC4S/R3KvlMTyiBjr5T6LqWGj9bq6nvpM0KBsoeYtr4OdCLITFX5GojuO4VpB
Hy11n8zc9JcAx4IFW0Aw0/DfCmMDvIomQItBAaIWewZqNHc0UwS0y/JRhAe8SiTz5sFJ6Abvgax6
vEfbYT0gzok+qtlfBNQLPvXejquhc0pZBaX1RgKDZyEJh3DBVRaFDgogK8XphaI/xtd1Cww9uO63
QxA7HfrFUN8rJXrHF4EMi/yrDxs2xVHGF0v21xeuXRwLW9JXYn4fFAJJ0Jr8N5f03UDuKeNlI568
RFVOGH7WpOLvKN4CDlsC+DT4Z8YVIOdtS/tO+Q==
D/MainActivity: Decrypt = This is a text
UPDATE
For Android API 19, you just have to use the previous KeyStore API KeyPairGeneratorSpec instead of KeyGenParameterSpec like this:
try {
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 1);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
.setAlias("key1")
.setSubject(new X500Principal("CN=Sample Name, O=Android Authority"))
.setSerialNumber(BigInteger.ONE)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
generator.initialize(spec);
// error in android 6: InvalidKeyException: Need RSA private or public key AndroidOpenSSL
// error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround
String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround";
KeyPair keyPair = generator.generateKeyPair();
Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
inCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
outCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
String plainText = "This is a text";
cipherOutputStream.write(plainText.getBytes("UTF-8"));
cipherOutputStream.close();
String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
Log.d(TAG, "Encrypt = " + ecryptedText);
String cipherText = ecryptedText;
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
String finalText = new String(bytes, 0, bytes.length, "UTF-8");
Log.d(TAG, "Decrypt = " + finalText);
} catch (javax.crypto.NoSuchPaddingException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (NoSuchProviderException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (InvalidAlgorithmParameterException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (InvalidKeyException e) {
Log.e(TAG, Log.getStackTraceString(e));
} catch (UnsupportedOperationException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
Please help this is so important for me.
I want encrypt and decrypt querystring with digital signature but I get this error:
Bad data error
Please help This is my encrypt code:
public partial class HashQueryString : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
RSACryptoServiceProvider senderCipher = new RSACryptoServiceProvider();
senderCipher.FromXmlString(SENDER_KEYS);
RSACryptoServiceProvider receiverCipher = new RSACryptoServiceProvider();
senderCipher.FromXmlString(RECEIVER_PUBLIC_KEY);
string plainText = "milad";
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] cipherTextBytes = receiverCipher.Encrypt(plainTextBytes, false);
SHA1Managed hashalg = new SHA1Managed();
byte[] hash = hashalg.ComputeHash(cipherTextBytes);
RSAPKCS1SignatureFormatter sigFormatter = new RSAPKCS1SignatureFormatter(senderCipher);
sigFormatter.SetHashAlgorithm("SHA1");
byte[] signature = sigFormatter.CreateSignature(hash);
string ciphertext = Convert.ToBase64String(cipherTextBytes);
string signatureText = Convert.ToBase64String(signature);
hlDecrypt.NavigateUrl = "/DeHashQueryString.aspx?secret=" + Server.UrlEncode(ciphertext) + "&signature=" + Server.UrlEncode(signatureText) + "";
}
catch (CryptographicException x)
{
MessageBox.Show(x.StackTrace+"");
}
}
}
And this is my decrypt code
public partial class DeHashQueryString : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string secret = Request.QueryString["secret"];
if (secret == null)
{
throw new ApplicationException("Secret QueryString was not provided...");
}
string signature = Request.QueryString["signature"];
if (signature == null)
{
throw new ApplicationException("Signature was not found...");
}
byte[] cipherText = Convert.FromBase64String(secret);
byte[] signatureBytes = Convert.FromBase64String(signature);
SHA1Managed hashalg = new SHA1Managed();
byte[] computedhash = hashalg.ComputeHash(cipherText);
RSACryptoServiceProvider senderCipher = new RSACryptoServiceProvider();
senderCipher.FromXmlString(SENDER_PUBLIC_KEYS);
RSAPKCS1SignatureDeformatter sigDeFormatter = new RSAPKCS1SignatureDeformatter(senderCipher);
sigDeFormatter.SetHashAlgorithm("SHA1");
if (!sigDeFormatter.VerifySignature(computedhash, signatureBytes))
{
throw new ApplicationException("Signature did not match from sender...");
}
decrypt(cipherText, RECEIVER_KEY);
}
private void decrypt(byte[] cipherText,string key)
{
RSACryptoServiceProvider cipher =new RSACryptoServiceProvider();
cipher.FromXmlString(key);
string str = Convert.ToBase64String(cipherText);
byte[]plainTextBytes=cipher.Decrypt(Convert.FromBase64String(str), false);
Response.Write("My querystring was :" + Encoding.UTF8.GetString(plainTextBytes));
}
}
I write public/private key values completely
I delete public/private key value
This is receiver_public_key:
private const string RECEIVER_PUBLIC_KEY = "zUjNd9zRuTluiiwiLu47SiIgvGl8+YQPKuyklmwXzdH8WYP2VAWIR2rpRUIsNIv/2LMLlKM69KXCIkn9SQZ0XsetAQqUK0VKO9DLUtgkJ4loSq+V6BGhpdNzjKYObdXz00g12HukV/Wq4kslB9/ghgkCmQmC1mkxaCOPtQVcBfk=AQAB6Q+Ro8TpTeT0eid9KImBsesRHGejTPxb6BCOhxMXd6RlD0BMrNk+wU62f09sVy3O55AML5fKX79d6kWDFIRDTQ==4X1Z64BdfMFI7ffnneCIquObQ9A/mf40omjsnKuk+Sx2+VGQFc7VNaA9/hpeJ+cjAnUCM+LNDoNb8jAntq5fXQ==bcooyKZlZY164eSiYCtOzpq259OmqQik3xCVo+oJfxIRjXqz5CU/G99Rt22Z0wPAWXORWgY+jpZezpLKairYbQ==Wl15478VuCFdsMBgugx5uMJuPsb+NiCBx3R1HnRLMPB43YGqVJMHLu6A6Yx3n1Yp2Zo6v8BsnRxXhL93quZGoQ==kRyYgXh/aWJdk6w2AeootIwSuok6K2yfVR0kBXsEGMJzUafpZ9M6JFL+QpoeEbrxmkh3H4IhUcJiFF59Izxo7w==f+P0RdFnQwrZp/E41p4Kh/PdCyR4/IXeYTKOkzwCVHKW0TnaM5xCu6OKcmB4Y8A4g0uAUnii2RmPaYdI6b7ArdHwtBFfJA6Xrn6NZkLa/SP1DGCLxZI+B4+wY0oY1f6ZGwol4kPrvXysnclG9kUgb0YjVMZ9aqcwHZkkSuzTLhE=";
And this is sender_key:
"zUjNd9zRuTluiiwiLu47SiIgvGl8+YQPKuyklmwXzdH8WYP2VAWIR2rpRUIsNIv/2LMLlKM69KXCIkn9SQZ0XsetAQqUK0VKO9DLUtgkJ4loSq+V6BGhpdNzjKYObdXz00g12HukV/Wq4kslB9/ghgkCmQmC1mkxaCOPtQVcBfk=AQAB";