I'm using RSA encryption for converting simpletext to encrypted form.
my plain text is : hello
encrypted text : [B#d7eed7
Now, how to convert encrypted text into simple plain text
i'm using following code
KeyPairGenerator keygenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
keygenerator.initialize(1024, random);
KeyPair keypair = keygenerator.generateKeyPair();
PrivateKey privateKey = keypair.getPrivate();
PublicKey publicKey = keypair.getPublic();
Cipher cipher = Cipher.getInstance("RSA");
String arrayStr = "[b#d7eed7";
byte ciphertext = arrayStr.getBytes();
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] cleartext1 = cipher.doFinal(ciphertext);
System.out.println("the decrypted cleartext is: " + new String(cleartext1));
i'm getting javax.crypto.BadPaddingException: Data must start with zero
need help !!
The problem is that [B#d7eed7 is not the encrypted text. It simply shows the type and the address of the byte array, not its contents.
For more information, see https://stackoverflow.com/a/5500020/367273
I just looked to the "Related" part on the right side of the screen and... Convert Java string to byte array
to convert string to byte array you can use the following:
String source = "0123456789";
byte[] byteArray = source.getBytes("specify encoding alongside endianess");// e.g "UTF-16LE", "UTF-16"..
For more info you can check here, here and here.
Good luck!
Related
This might be a duplicate of this answered question, but I can't seem to get the same results. Hoping for some guidance here.
JSEncrypt (client)
let encrypt = new Encrypt.JSEncrypt();
encrypt.setPublicKey(this.publicKey); // retrieved from server
encrypt.encrypt(password);
BouncyCastle (server) - RSA key generation
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
KeyPair pair = generator.generateKeyPair();
PublicKey pubKey = pair.getPublic();
PrivateKey privKey = pair.getPrivate();
// returned to client
String publicKeyStr = new String(Base64.encodeBase64(pubKey.getEncoded()));
String privateKeyStr = new String(Base64.encodeBase64(privKey.getEncoded()));
BouncyCastle (server) - Decryption
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// org.apache.commons.codec.binary.Hex
byte[] cipherText = cipher.doFinal(Hex.decodeHex(encrypted.toCharArray()));
decrypted = new String(cipherText, BaseConstant.ENC_UTF8);
Error
org.apache.commons.codec.DecoderException: Illegal hexadecimal character I at index 0
at org.apache.commons.codec.binary.Hex.toDigit(Hex.java:178)
at org.apache.commons.codec.binary.Hex.decodeHex(Hex.java:89)
One thing I noticed is the length of encrypted text by JSEncrypt, which is 172, while encryption at server side produces 256.
The answered question mentioned to use RSA/None/PKCS1Padding, which I had already set. What else could I be missing?
The error occurs in Hex.decodeHex() method, which means that your data is not a Hex encoded string.
JSEncrypt.encrypt() method returns the encrypted data in Base64 (instead of Hex string). In order to decrypt it, you must decode it from base64 format.
So instead of:
byte[] cipherText = cipher.doFinal(Hex.decodeHex(encrypted.toCharArray()));
Do this:
byte[] cipherText = cipher.doFinal(Base64.decodeBase64(encrypted.toCharArray()));
You can also solve this problem just from the client side. See the code below:
let encrypt = new Encrypt.JSEncrypt();
encrypt.setPublicKey(this.publicKey);
encrypt.getKey().encrypt(password);
Just add getKey() after encrypt. It worked for me! I encrypted my password into Hex string using this approach.
I want to encode a string with rsa/ecb/pkcs1 padding mode with a given public key (the public key is a string) in java.
I also want to present the results in UTF-8 Format
how to do it?
i have done this code:
String pub = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4IJZLsjlx+o4RSvafaAcReoNnzrI0UXu7kZyXPe31ql32X9AvhC6QQIUmLkr1Evm0zP/SgVG9YX3DSqBUgPo04iv1I1/wNKwAf1/uH9EiiqdpczefyxxnzJiKUTcx2/4mA4E4QxCIL5JsZb78WoYZrd2kToW/WD01MnSFiCgSyjGdd812GY2EVzfvlv8kYuti3icMUyitEfHhtw8cAWI6/nVrRPNs0e5NsvtZJ0nfrXsfQDR0C7+ivQK+fQabi8oRGsbTZceAvVlqVE669zoIwIFLcB+eYXTxbka4E7veUMpaF9w//HdwVS2y/2jJiI+16qPStQQPIKQ4Cucoif7/UHfIBuVGVJ5MIVyK7NC7TV/lyoXmyo7ZcnVZnI7rZcw5/qZcqaZ0VCrzvHijwTK7100hOOjiarvRa2OJGXHLIeAUlbrHOXEXS6ah2glPhLDEg6Qzp/lKVSISolal7q73qyhF483P9jXn3hefSLA9J1/1LgeajWvuVkxuw+dy2Tlv7oUpNBkX47/TOho5qttr1y9K3hD5Q87RAJPdBtFdDbY8qUPxoiBsTbUWjVoEjJf2YAsLTJIIi2ZISkbD/VdrtZnS73QSJkJReOMNT9XYNGDJvwNIrRcNGFKlJcX6qq+ozGNsDkrt0ObxAD7YCTjAYQVTlbQOaTu5DbGxGDNCoMCAwEAAQ==";
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] keyBytes = Base64.getDecoder().decode(pub.getBytes("UTF-8"));
PKCS1EncodedKeySpec KeySpec = new PKCS1EncodedKeySpec(keyBytes);
RSAPublicKey publicKey = (RSAPublicKey)keyFactory.generatePublic((java.security.spec.KeySpec) KeySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherData = cipher.doFinal(text.getBytes("UTF-8"));
return cipherData;
But it doesnot work..
it is said that Invalid DER: object is not integer
Assuming you're using a valid RSA key, you'll need to:
Convert your public key from a string to an actual public key object
//This code is incorrect. You'll need bouncy castle for PKCS1
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] keyBytes = Base64().getDecoder.decode(publicKey.getBytes()); //assuming base64 encoded key
PKCS1EncodedKeySpec KeySpec = new PKCS1EncodedKeySpec(keyBytes);
RSAPublicKey publicKey = (RSAPublicKey)keyFactory.generatePublic(KeySpec);
Get the bytes of your plain text
Encrypt using your public key
Encode to a readable format.
Check out this answer for steps 1-3: RSA Encrypt/Decrypt in Java. Remember to use the correct algorithm spec, in your case PKCS1
Chances are your cipher text will not use only UTF-8 characters so you'll probably want to use Base 64 encoded text to display your cipher text. Base 64 is able to display all those wonky characters as ascii values.
Simply use: Base64.getEncoder().encodeToString(cipherTextBytes)
I want to create a RSA key pair and use it for encoding/decoding data. My code is quite short but I cannot find any error.
Can anyone help me finding my problem?
Thanks for every hint!
// Generate key pair.
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024, new SecureRandom());
KeyPair keyPair = kpg.genKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// Data to encode/decode.
byte[] original = "The quick brown fox jumps over the lazy dog.".getBytes("UTF8");
// Encode data with public key.
Cipher cipherEncoder = Cipher.getInstance("RSA/ECB/NoPadding");
cipherEncoder.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encodedData = cipherEncoder.doFinal(original);
// Decode data with private key.
Cipher cipherDecoder = Cipher.getInstance("RSA/ECB/NoPadding");
cipherDecoder.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decodedData = cipherEncoder.doFinal(encodedData);
// Output.
System.out.println(new String("Original data: " + new String(original, "UTF8")));
System.out.println(new String("Encoded/decoded: " + new String(decodedData, "UTF8")));
The output at the end seems to be quirky.
Firstly, you are using the cipherEncoder to decode your data. You probably meant to use cipherDecoder. Secondly, you are going to have issues using RSA without padding (namely, your data will have a load of 0 bytes at the start). I would recommend you at least use PKCS1 padding. Here is the code after those changes.
// Generate key pair.
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024, new SecureRandom());
KeyPair keyPair = kpg.genKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// Data to encode/decode.
byte[] original = "The quick brown fox jumps over the lazy dog.".getBytes("UTF8");
// Encode data with public key.
Cipher cipherEncoder = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipherEncoder.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encodedData = cipherEncoder.doFinal(original);
// Decode data with private key.
Cipher cipherDecoder = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipherDecoder.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decodedData = cipherDecoder.doFinal(encodedData);
// Output.
System.out.println(new String("Original data: " + new String(original, "UTF8")));
System.out.println(new String("Encoded/decoded: " + new String(decodedData, "UTF8")));
My aim is to write a Java program to encrypt a text file (cipher text) using AES algorithm. And then, write another program to decrypt that encrypted file (cipher text) to get the plain text back. I want to use same key (same key, generate once, save it somewhere, and use it in both encryption and decryption program) for encryption and decryption process. If I generate key and do the encryption and decryption line by line in the same program then it works perfectly. Here is the working code snippet for that:
String strDataToEncrypt = new String();
String strCipherText = new String();
String strDecryptedText = new String();
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE,secretKey);
strDataToEncrypt = "any text input";
byte[] byteDataToEncrypt = strDataToEncrypt.getBytes();
byte[] byteCipherText = aesCipher.doFinal(byteDataToEncrypt);
strCipherText = new BASE64Encoder().encode(byteCipherText);
System.out.println("cipher text: " +strCipherText);
aesCipher.init(Cipher.DECRYPT_MODE,secretKey,aesCipher.getParameters());
byte[] byteDecryptedText = aesCipher.doFinal(new BASE64Decoder().decodeBuffer(strCipherText));
strDecryptedText = new String(byteDecryptedText);
System.out.println("plain text again: " +strDecryptedText);
But, I need to have two different programs (java files) for encryption and decryption. So, I have to somehow generate a key and save that somewhere. Then use the same key for both encryption and decryption program. How can I do that?
EDIT_1
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
byte[] encoded = secretKey.getEncoded();
System.out.println("key: "+encoded);// key: [B#52b2a2d8
I can get the encoded key value using the above program. But my question is how to generate the SecretKey using this value in my decryption program?
Forgive me if I misunderstood your question but I believe you wish to reconstruct a SecretKey object from a existing key encoded in a byte array.
This can be performed simply by using the javax.crypto.spec.SecretKeySpec's constructor as such:
byte[] encoded = //Key data
SecretKey secretKey = new SecretKeySpec(encoded, "AES");
Since SecretKeySpec is a subclass of SecretKey no casting is needed. Should your encryption/decrption algorithm change please make sure to change the string literal used in the constructor AES to whatever algorithm you decided to use in the future.
Here's one way to print out the values in a byte[] array in hex:
byte[] a = {-120, 17, 42,121};
for (byte b : a)
{
System.out.printf("%2X",b);
}
System.out.println();
I use the following code to encrypt some data and I want to move the decryption code to a server so need to send the cipherData (which is a byte [] array ) to my server over REST
BigInteger modulus = new BigInteger("blah");
BigInteger exponent = new BigInteger("blah");
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory encryptfact = KeyFactory.getInstance("RSA");
PublicKey pubKey = encryptfact.generatePublic(keySpec);
String dataToEncrypt = "Hello World";
/**
* Encrypt data
*/
Cipher encrypt = Cipher.getInstance("RSA");
encrypt.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = encrypt.doFinal(dataToEncrypt.getBytes());
System.out.println("cipherData: " + new String(cipherData));
/**
* Decrypt data
*/
BigInteger privatemodulus = new BigInteger("blah");
BigInteger privateexponent = new BigInteger("blah");
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(privatemodulus, privateexponent);
PrivateKey privateKey = encryptfact.generatePrivate(privateKeySpec);
Cipher decrypt = Cipher.getInstance("RSA");
decrypt.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decData = decrypt.doFinal(cipherData);
System.out.println(new String(decData));
This works fine.
I was hoping I could just create a new String with the cipherData as a parm
When I try this with the above example I get the following error
byte[] decData = decrypt.doFinal(new String(cipherData).getBytes());
javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:308)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:255)
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at com.test.EncryptTest.main(EncryptTest.java:52)
Any ideas?
I was hoping I could just create a new String with the cipherData as a parm
No. cipherData is arbitrary binary data. It's not encoded text, which is what the various String constructors expect. (As an aside, you should almost never call the String.getBytes() or new String(byte[]) which don't specify an encoding. Always specify an appropriate encoding, which will depend on the situation.)
Either transmit the data as binary data instead of going through text at all, or use Base64 to safely encode the binary data as text first, then decode it from Base64 to binary again later before decrypting. There's a public domain Base64 encoder which is easy to use.