gpt4 book ai didi

Java AES/CFB8/NoPadding 加密和字符集

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:29:52 26 4
gpt4 key购买 nike

我正在尝试用 Java 和 PHP 加密和解密 Strings,所以我使用 AES/CFB8/NoPadding,这对双方都有效。

现在我的 Cryptor 可以很好地处理拉丁字符,只要我将字符集设置为拉丁字符即可。但是当我将它设置为 UTF-8(这是我在我的数据库中使用的)时,加密没有正确完成。

这是输出:

/*
* Latin (ISO-8859-1) output:
* Original: MiiiMüäöMeeʞ
* Encoded: rQ¶[ÉÐRíD
* Decoded: MiiiMüäöMee?
*
* UTF-8 output:
* Original: MiiiMüäöMeeʞ
* Encoded: rQ�[�
* Decoded: Mii0SS1])_�ELJI�S�;�W��W?*
*/

因为“ʞ”不是拉丁字符,我知道它不能被正确加密。但为什么 UTF-8 不起作用?

public class Cryptor {

private Cipher cipher;
private String secretKey = "1234567890qwertz";
private String iv = "1234567890qwertz";

private SecretKey keySpec;
private IvParameterSpec ivSpec;
private Charset CHARSET = Charset.forName("ISO-8859-1"); // ISO-8859-1 vs. UTF-8

public Cryptor() throws CryptingException {

keySpec = new SecretKeySpec(secretKey.getBytes(CHARSET), "AES");
ivSpec = new IvParameterSpec(iv.getBytes(CHARSET));
try {
cipher = Cipher.getInstance("AES/CFB8/NoPadding");
} catch (NoSuchAlgorithmException e) {
throw new SecurityException(e);
} catch (NoSuchPaddingException e) {
throw new SecurityException(e);
}
}

public String decrypt(String input) throws CryptingException {

try {
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
return new String(cipher.doFinal(input.getBytes(CHARSET)), CHARSET).trim();
} catch (IllegalBlockSizeException e) {
throw new SecurityException(e);
} catch (BadPaddingException e) {
throw new SecurityException(e);
} catch (InvalidKeyException e) {
throw new SecurityException(e);
} catch (InvalidAlgorithmParameterException e) {
throw new SecurityException(e);
}
}

public String encrypt(String input) throws CryptingException {
try {
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
return new String(cipher.doFinal(input.getBytes(CHARSET)), CHARSET).trim();
} catch (InvalidKeyException e) {
throw new SecurityException(e);
} catch (InvalidAlgorithmParameterException e) {
throw new SecurityException(e);
} catch (IllegalBlockSizeException e) {
throw new SecurityException(e);
} catch (BadPaddingException e) {
throw new SecurityException(e);
}
}

public static void main(String Args[]) {

try {
Cryptor c = new Cryptor();
String original = "MiiiMüäöMeeʞ";
System.out.println("Original: " + original);
String encrypted = c.encrypt("MiiiMüäöMeeʞ");
System.out.println("Encoded: " + encrypted);
System.out.println("Decoded: " + c.decrypt(encrypted));

} catch (CryptingException e) {
e.printStackTrace();
}
}

class CryptingException extends RuntimeException {

private static final long serialVersionUID = 7123322995084333687L;

public CryptingException() {
super();
}

public CryptingException(String message) {
super(message);
}
}
}

最佳答案

我认为将加密的字节转换为 String 是个坏主意。这些字节对任何编码都无效,它们是随机的。

您需要将生成的 byte[] 编码为 base64 以获得一致的结果。请参阅 sun.misc.BASE64Encoder/sun.misc.BASE64Decoder

Here是一个将 base64 String 解码为 byte[] 的例子,逆向过程非常相似。

你可以声明解码器/编码器和类的顶部:

private final BASE64Decoder base64Decoder = new BASE64Decoder();
private final BASE64Encoder base64Encoder = new BASE64Encoder();

然后在你的decypt方法中你需要调用

return new String(cipher.doFinal(base64Decoder.decodeBuffer(input)), CHARSET);

在你的encrypt 方法中

return base64Encoder.encode(cipher.doFinal(input.getBytes(CHARSET)));

使用 UTF-8 输出:

Original: MiiiMüäöMeeʞ
Encoded: clEUtlv2ALXsKYw4ivOfwQ==
Decoded: MiiiMüäöMeeʞ

一方面要注意的是,严格来说使用来自 sun.* 的包不是好的做法,因为它们不是 java 规范的一部分,因此可能会更改/消失从一个版本到另一个版本。

Here是一篇关于迁移到 Apache Commons Codec 实现的小文章。
这也是a similar Guava API 中的类。

关于Java AES/CFB8/NoPadding 加密和字符集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15906041/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com