When Dycrypt plain text then throw BadPaddingException
javax.crypto.BadPaddingException: Given final block not properly padded
com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
private static final String ENCRYPTION_KEY = "harshitorld!##$%";
private static byte[] randomBytesToDecrypt;
private static final String ALGORITHM = "Rijndael";
private static final String UNICODE_FORMAT = "UTF8";
private static String encrypt(String value) {
try {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encValue = c.doFinal(value.getBytes(UNICODE_FORMAT));
String encryptedValue = new BASE64Encoder().encode(encValue);
return encryptedValue;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String encryptedValue) {
try {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue);
byte[] decValue = c.doFinal(decordedValue);//////////LINE 50
String decryptedValue = new String(decValue,UNICODE_FORMAT);
return decryptedValue;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
private static Key generateKey() throws Exception {
byte[] keyAsBytes;
keyAsBytes = ENCRYPTION_KEY.getBytes(UNICODE_FORMAT);
Key key = new SecretKeySpec(keyAsBytes, ALGORITHM);
return key;
}
public static String encryptText(String normalText) {
return encrypt(normalText);
}
public static String decryptText(String encryptedText) {
return decrypt(encryptedText);
}
Related
I'm trying to learn RSA public/private key-pair encryption in Java.
I have the code below working. It generates a private & public key pair, writes the keys to disk, encrypts the string with the public key from disk, the decrypts with the private key from disk, and then it outputs the decrypted string.
All works great.
The next thing is, I want the key files to be the readable "-----BEGIN RSA PRIVATE KEY-----" type of key files ... so I wrote the method saveKeysToDiskBase64.
The problem is, when I write the files using saveKeysToDiskBase64, the methods that read the key files fail. That is loadPrivateKey and loadPublicKey can't read the Base64 files.
What am I missing?
public class EncryptionTest1 {
public void execute() throws Exception {
String filename = "test1";
KeyPair keyPair = EncryptionUtil.generateKeyPair();
EncryptionUtil.saveKeysToDisk(filename, keyPair);
// EncryptionUtil.saveKeysToDiskBase64(filename, keyPair);
String pvtKeyFilename = filename+".key";
String pubKeyFilename = filename+".pub";
PrivateKey privateKey = EncryptionUtil.loadPrivateKey(pvtKeyFilename);
byte[] bPrivateKey = privateKey.getEncoded();
PublicKey publicKey = EncryptionUtil.loadPublicKey(pubKeyFilename);
byte[] bPublicKey = publicKey.getEncoded();
String sOriginal = "hi this is plain text";
byte[] encryptedData = EncryptionUtil.encrypt(bPublicKey, sOriginal.getBytes());
byte[] decryptedData = EncryptionUtil.decrypt(bPrivateKey, encryptedData);
String sEncrypted = new String(encryptedData);
String sDecrypted = new String(decryptedData);
System.out.println("sOriginal = "+sOriginal);
System.out.println("sEncrypted = "+sEncrypted);
System.out.println("sDecryptedData = "+sDecrypted);
}
public static void main(String[] args) {
try {
new EncryptionTest1().execute();
} catch (Exception x) {
x.printStackTrace();
}
}
}
...
public class EncryptionUtil {
private static final String ALGORITHM = "RSA";
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
// 2048 is keysize
keyGen.initialize(2048, random);
KeyPair generateKeyPair = keyGen.generateKeyPair();
return generateKeyPair;
}
public static void saveKeysToDisk(String name, KeyPair keyPair) {
try {
String privateFileName = name+".key";
FileOutputStream out1 = new FileOutputStream(privateFileName);
out1.write(keyPair.getPrivate().getEncoded());
out1.close();
String publicFileName = name+".pub";
FileOutputStream out2 = new FileOutputStream(publicFileName);
out2.write(keyPair.getPublic().getEncoded());
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static void saveKeysToDiskBase64(String name, KeyPair keyPair) {
try {
Base64.Encoder encoder = Base64.getEncoder();
String privateFileName = name+".key";
Writer out = new FileWriter(privateFileName);
out.write("-----BEGIN RSA PRIVATE KEY-----\n");
out.write(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
out.write("\n-----END RSA PRIVATE KEY-----\n");
out.close();
String publicFileName = name+".pub";
Writer out2 = new FileWriter(publicFileName);
out2.write("-----BEGIN RSA PUBLIC KEY-----\n");
out2.write(encoder.encodeToString(keyPair.getPublic().getEncoded()));
out2.write("\n-----END RSA PUBLIC KEY-----\n");
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static PrivateKey loadPrivateKey(String keyFile) {
PrivateKey pvt = null;
try {
/* Read all bytes from the private key file */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
/* Generate private key. */
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pvt = kf.generatePrivate(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pvt;
}
public static PublicKey loadPublicKey(String keyFile) {
PublicKey pub = null;
try {
/* Read all the public key bytes */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
/* Generate public key. */
X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pub = kf.generatePublic(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pub;
}
public static byte[] encrypt(byte[] publicKey, byte[] inputData) throws Exception {
PublicKey key = KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(publicKey));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(inputData);
return encryptedBytes;
}
public static byte[] decrypt(byte[] privateKey, byte[] inputData) throws Exception {
PrivateKey key = KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(privateKey));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = cipher.doFinal(inputData);
return decryptedBytes;
}
}
Great thanks to #President James K. Polk who gave me the correct answer in a comment.
Here is the Base64 related code that that worked for me ...
private static String PRIVATE_HEADER = "-----BEGIN PRIVATE KEY-----\n";
private static String PRIVATE_FOOTER = "\n-----END PRIVATE KEY-----\n";
private static String PUBLIC_HEADER = "-----BEGIN PUBLIC KEY-----\n";
private static String PUBLIC_FOOTER = "\n-----END PUBLIC KEY-----\n";
public static void saveKeysToDiskBase64(String name, KeyPair keyPair) {
try {
Base64.Encoder encoder = Base64.getEncoder();
String privateFileName = name+".key";
Writer out = new FileWriter(privateFileName);
out.write(PRIVATE_HEADER);
out.write(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
out.write(PRIVATE_FOOTER);
out.close();
String publicFileName = name+".pub";
Writer out2 = new FileWriter(publicFileName);
out2.write(PUBLIC_HEADER);
out2.write(encoder.encodeToString(keyPair.getPublic().getEncoded()));
out2.write(PUBLIC_FOOTER);
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static PrivateKey loadPrivateKeyBase64(String keyFile) {
PrivateKey pvt = null;
try {
/* Read all bytes from the private key file */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
String s = new String(bytes);
s = s.replace(PRIVATE_HEADER, "");
s = s.replace(PRIVATE_FOOTER, "");
bytes = Base64.getDecoder().decode(s.getBytes());
/* Generate private key. */
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pvt = kf.generatePrivate(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pvt;
}
public static PublicKey loadPublicKeyBase64(String keyFile) {
PublicKey pub = null;
try {
/* Read all the public key bytes */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
String s = new String(bytes);
s = s.replace(PUBLIC_HEADER, "");
s = s.replace(PUBLIC_FOOTER, "");
bytes = Base64.getDecoder().decode(s.getBytes());
/* Generate public key. */
X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pub = kf.generatePublic(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pub;
}
public void handleResult(Result result) {
final String scanResult = result.getText();
Log.e("QRCode:", scanResult);
String normalTextDec = null;
try {
normalTextDec = AESHelper.decrypt(seedValue, scanResult);
Log.e("Decrypt:",normalTextDec);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In the above code "scanResult" is the encrypted String. I wanted to decrypt it. When I am printing scanResult on the console it is giving the correct encrypted String but decryption is not working. Can anyone solve this? And I am using AESHelper class for this.
AESHelper class:
public class AESHelper {
public static String encrypt(String seed, String cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String seed, String encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b)
{
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
}
If I am using the following methods to encrypt and decrypt a String...
Shouldn't the seed value be a 'secret' and not 'hard-codded'?
And if so... how would I achieve that goal?
String encryption(String userText){
String seedValue = "SecretKey";
String userTextEncrypted="";
try {
userTextEncrypted = AESHelper.encrypt(seedValue, userText);
} catch (Exception e) {
e.printStackTrace();
}
return userTextEncrypted;
}
String decryption(String encryptedText){
String seedValue = "SecretKey";
String decryptedText="";
try {
decryptedText = AESHelper.decrypt(seedValue, encryptedText);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedText;
}
Below is the AESHelper class...
public class AESHelper {
public static String encrypt(String seed, String cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String seed, String encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG","Crypto");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
}
I'm trying to implement a Cipher-Encryption/Decryption class.
Testing it:
System.out.println(MysteryHandler.decrypt(MysteryHandler.encrypt("I like programming!")));
But the result-String is this: >�տm����s��ng!
Class:
public class MysteryHandler {
private static SecretKey secretKey;
private static Cipher cipher;
private static byte[] utf8Bytes;
/**Verschluesseln*/
public static byte[] encrypt(String plainText){
try {
secretKey = KeyGenerator.getInstance("AES").generateKey();
cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
utf8Bytes = plainText.getBytes("UTF8");
return cipher.doFinal(utf8Bytes);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**Entschluesseln*/
public static String decrypt(byte[] secret){
try {
cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(secret, secret.length - 16, 16));
utf8Bytes = cipher.doFinal(secret);
return new String(utf8Bytes, "UTF8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
What am I doing wrong?
I get error when I try to decode.
This is Decoder:
public class Encrypter {
Cipher ecipher;
Cipher dcipher;
SecretKeySpec key = new SecretKeySpec("missyou1".getBytes(), "DES");
public DesEncrypter() throws Exception {
ecipher = Cipher.getInstance("DES");
dcipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, key);
dcipher.init(Cipher.DECRYPT_MODE, key);
}
public String encrypt(String str) throws Exception {
byte[] utf8 = str.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
return new sun.misc.BASE64Encoder().encode(enc);
}
public String decrypt(String str) throws Exception {
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
byte[] asd = new byte[(dec.length/8+1)*8];
for(int i = 0; i < dec.length; i++){
asd[i] = dec[i];
}
byte[] utf8 = dcipher.doFinal(asd);
return new String(utf8, "UTF8");
}
}
This is code where I get error:
private static void appenda(Encrypter encrypt) {
if (Files.exists(Paths.get(filePath), new LinkOption[] { LinkOption.NOFOLLOW_LINKS })) {
Stream<String> stringStream = null;
try {
stringStream = Files.lines(Paths.get(filePath), StandardCharsets.UTF_8);
} catch (IOException e) {
LOGGER.error("Failed ", e);
}
if (stringStream.toString() != null) {
stringStream.forEach(s -> {
try {
System.out.println(encrypt.decrypt(s));
endpoint.delete(0, endpoint.length());
endpoint.append(encrypt.decrypt(s));
} catch (Exception e) {
LOGGER.error("Failed to decrypt", e);
}
});
}
}
}
in line endpoint.append(encrypter.decrypt(s));
Any idea why?
Its not working because you are needlessly copying the data into an incorrectly sized array.
Just remove the array copy and decrypt the bytes directly.
public String decrypt(String str) throws Exception {
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
byte[] utf8 = dcipher.doFinal(dec);
return new String(utf8, "UTF8");
}