我想加密和解密密码使用128位AES加密与16字节的密钥。在解密值时,我得到javax.crypto.BadPaddingException
错误。我在解密的时候漏掉了什么吗?
public static void main(String args[]) {
Test t = new Test();
String encrypt = new String(t.encrypt("mypassword"));
System.out.println("decrypted value:" + t.decrypt("ThisIsASecretKey", encrypt));
}
public String encrypt(String value) {
try {
byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string:" + (new String(encrypted)));
return new String(skeySpec.getEncoded());
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public String decrypt(String key, String encrypted) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(skeySpec.getEncoded(), "AES"));
//getting error here
byte[] original = cipher.doFinal(encrypted.getBytes());
return new String(original);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
错误信息
encrypted string:�Bj�.�Ntk�F�`�
encrypted key:ThisIsASecretKey
decrypted value:null
May 25, 2012 12:54:02 PM bean.Test decrypt
SEVERE: null
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at bean.Test.decrypt(Test.java:55)
at bean.Test.main(Test.java:24)
public class Test {
public String encryptionKey;
public static void main(String args[]) {
Test t = new Test();
String encrypt = t.encrypt("mypassword");
System.out.println("decrypted value:" + t.decrypt(t.encryptionKey, encrypt));
}
public String encrypt(String value) {
try {
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(256);
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
String key = new Base64().encodeAsString(raw);
this.encryptionKey = key;
System.out.println("------------------Key------------------");
System.out.println(key);
System.out.println("--------------End of Key---------------");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
String encrypt = (new Base64()).encodeAsString(cipher.doFinal(value.getBytes()));
System.out.println("encrypted string:" + encrypt);
return encrypt;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public String decrypt(String key, String encrypted) {
try {
Key k = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, k);
byte[] decodedValue = Base64.getDecoder().decode(encrypted);
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
如果对于分组密码,您不打算使用包含填充方案的cipher
转换,则需要使明文中的字节数是密码块大小的整数倍。
因此,要么将明文填充到16字节的倍数(这是AES块大小),要么在创建cipher
对象时指定填充方案。例如,您可以使用:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
除非您有充分的理由不这样做,否则请使用JCE实现中已经包含的填充方案。他们已经想出了许多微妙的情况和角落,你必须意识到和处理自己否则。
String s = new String(someBytes);
byte[] retrievedBytes = s.getBytes();
SomeBytes
和RetrievedBytes
不会相同。
如果您希望/必须将密文保存在字符串
中,那么base64首先对密文字节进行编码,然后从base64编码的字节构造字符串
。然后在解密时,您将getBytes()
从字符串中获取base64编码的字节
,然后base64-decode它们以获得真正的密文,然后对其进行解密。
这个问题的原因是大多数(全部?)字符编码不能将任意字节映射到有效字符。因此,当您从密文创建字符串
时,string
构造函数(应用字符编码将字节转换为字符)实际上必须丢弃一些字节,因为它对这些字节没有意义。因此,当您从字符串中获得字节时,它们与您放入字符串的字节不同。
在Java中(以及一般的现代编程中),您不能假设一个字符=一个字节,除非您完全知道您处理的是ASCII。这就是为什么如果要从任意字节构建字符串,就需要使用base64(或类似的东西)。
我有一个应用程序,需要在配置文件中存储一些秘密密码,如数据库和ftp密码/详细信息。我环顾四周,发现了许多使用AES的加密/解密解决方案,但我似乎不知道如何在不改变密钥的情况下使其工作。这意味着我可以加密和解密(使用相同的秘密密钥),但在重启等过程中保持持久性。我似乎无法让秘密钥匙保持不变。下面的示例显示了我的工作方法: 到目前为止还不错。然而,如果我运行它一次,我可能会得到'2Vhht/L80U
以下示例有什么问题? 问题是解密字符串的第一部分是无意义的。不过,其余的都很好,我明白了...
BK.Crypt 加解密模块 可以对字符串或byte数组进行MD5、HMAC-MD5、SHA1、HMAC-SHA1加密操作,结果以十六进制字符串或Base64字符串返回。 异步接口 md5ToHex(object) 将字符串进行md5 hash操作,结果以16进制字符串返回。 手Q版本:无版本要求 函数参数object: 属性名 类型 是否必填 说明 data string或Array\ 是 类型
我们封装了一个RSA 加解密的工具放在 extends 中。首先看看它的文件结构 rsa |-- RSACrypt 加解密主程序 |-- RSACryptBigData 大数据加解密 |-- SignUtil 签名类 |-- rsa_public_key.pem 公钥 |-- rsa_private_key.pem 私钥 RSACrypt API RSAC
加解密算法 算法类型 特点 优势 缺陷 代表算法 对称加密 加解密密钥相同或可推算 计算效率高,加密强度高 需提前共享密钥;易泄露 DES、3DES、AES、IDEA 非对称加密 加解密密钥不相关 无需提前共享密钥 计算效率低,仍存在中间人攻击可能 RSA、ElGamal、椭圆曲线系列算法 算法体系 现代加密算法的典型组件包括:加解密算法、加密密钥、解密密钥。其中,加解密算法自身是固定不变的,一般
配置 在使用 Lumens 的加解密前,你应该先把 .env 文件中的 APP_KEY 选项设置为 32 位随机字符串。如果没有适当地设置这个值,所有被 Lumen 加密的值都将是不安全的。 基本用法 加密一个值 你可以使用 Crypt 门面来加密一个值。所有的加密值都使用 OpenSSL 和 AES-256-CBC 来进行加密。 此外, 所有加密过的值都会使用消息认证码 (MAC)来进行签名,以