密码解密/加密变化结果
Cipher decryption / encryption changing results
我正在对一些解密数据的代码进行逆向工程,希望我能够将其加密并获得与开始时相同的数据,reasons that would make this question too long and off-topic。
public void Test() throws Exception {
String pk_enc = //...
String hashStr_64 = //...
byte[] hashStr_encrypted = Base64.decode(hashStr_64);
X509EncodedKeySpec e = new X509EncodedKeySpec(Base64.decode(pk_enc));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey RSApublicKey = (RSAPublicKey) keyFactory.generatePublic(e);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(2, RSApublicKey); // '2' means decrypt
byte[] hashStr_decrypted = cipher.doFinal(hashStr_encrypted);
String hashStr_result = new String(hashStr_decrypted);
// Now in reverse...
Cipher cipher1 = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
// instantiating a new cipher or using the original one makes no difference
cipher1.init(1, RSApublicKey); // '1' means encrypt
byte[] hashStr_encrypted_reverse = cipher1.doFinal(hashStr_decrypted);
String hashStr_64_reverse = Base64.encode(hashStr_encrypted_reverse);
}
// Now in reverse...
之前的所有代码都无法更改,但这并不意味着无法将hashStr_result
转换回hashStr_64
,对吗?
但是,我之后编写的代码本应做到这一点,但它不起作用。
hashStr_encrypted_reverse
不同于 hashStr_encrypted
。为什么会这样,我该如何解决?
另一个表明加密出错的迹象是如果我再次尝试解密会发生什么...
// Decrypt again
Cipher cipher2 = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher2.init(2, RSApublicKey);
byte[] hashStr_decrypted_again = cipher.doFinal(hashStr_encrypted_reverse);
这抛出:
javax.crypto.BadPaddingException
我不太在乎,但也许它可以帮助回答这个问题。
正如@JamesKPolk 在他的评论中所说,这不是 RSA 的工作方式。 RSA 是一种非对称 加密算法:有两个密钥,public 和私有。对称算法(例如 AES)有一个密钥,用于加密和解密,并且该密钥必须保持安全,发送方和接收方除外。
为什么非对称加密?
- 您可以使用 public 密钥(通常是其他人与您共享的密钥)进行加密,他们必须使用自己的私钥来解密。任何人都可以拥有 public 密钥(这就是为什么它是 public),但它不能用于读取加密的消息。这就是您遇到问题的地方。
- 此外,您可以使用私钥(通常是您自己的)加密消息,其他任何人都可以使用您的 public 密钥对其进行解密。这就是数字签名的实现方式:例如,您将加密一份文档的摘要,如果任何人拥有您的 public 密钥,他们都可以验证您的签名,但没有其他人可以签署它。
术语会令人困惑。有 4 个 RSA 操作,最好描述为:签名、验证、加密、解密。将这些映射到较低级别并仅使用加密和解密的语言,这些映射如下:
签名验证对
- 签名 -> 使用私钥加密
- 验证 -> 使用 public 密钥解密
加密-解密对
- 正在加密 -> 使用 public 密钥加密
- 解密 -> 用私钥解密。
如您所见,每一对操作的一侧都有私钥,另一侧有 public 密钥。
我正在对一些解密数据的代码进行逆向工程,希望我能够将其加密并获得与开始时相同的数据,reasons that would make this question too long and off-topic。
public void Test() throws Exception {
String pk_enc = //...
String hashStr_64 = //...
byte[] hashStr_encrypted = Base64.decode(hashStr_64);
X509EncodedKeySpec e = new X509EncodedKeySpec(Base64.decode(pk_enc));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey RSApublicKey = (RSAPublicKey) keyFactory.generatePublic(e);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(2, RSApublicKey); // '2' means decrypt
byte[] hashStr_decrypted = cipher.doFinal(hashStr_encrypted);
String hashStr_result = new String(hashStr_decrypted);
// Now in reverse...
Cipher cipher1 = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
// instantiating a new cipher or using the original one makes no difference
cipher1.init(1, RSApublicKey); // '1' means encrypt
byte[] hashStr_encrypted_reverse = cipher1.doFinal(hashStr_decrypted);
String hashStr_64_reverse = Base64.encode(hashStr_encrypted_reverse);
}
// Now in reverse...
之前的所有代码都无法更改,但这并不意味着无法将hashStr_result
转换回hashStr_64
,对吗?
但是,我之后编写的代码本应做到这一点,但它不起作用。
hashStr_encrypted_reverse
不同于 hashStr_encrypted
。为什么会这样,我该如何解决?
另一个表明加密出错的迹象是如果我再次尝试解密会发生什么...
// Decrypt again
Cipher cipher2 = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher2.init(2, RSApublicKey);
byte[] hashStr_decrypted_again = cipher.doFinal(hashStr_encrypted_reverse);
这抛出:
javax.crypto.BadPaddingException
我不太在乎,但也许它可以帮助回答这个问题。
正如@JamesKPolk 在他的评论中所说,这不是 RSA 的工作方式。 RSA 是一种非对称 加密算法:有两个密钥,public 和私有。对称算法(例如 AES)有一个密钥,用于加密和解密,并且该密钥必须保持安全,发送方和接收方除外。
为什么非对称加密?
- 您可以使用 public 密钥(通常是其他人与您共享的密钥)进行加密,他们必须使用自己的私钥来解密。任何人都可以拥有 public 密钥(这就是为什么它是 public),但它不能用于读取加密的消息。这就是您遇到问题的地方。
- 此外,您可以使用私钥(通常是您自己的)加密消息,其他任何人都可以使用您的 public 密钥对其进行解密。这就是数字签名的实现方式:例如,您将加密一份文档的摘要,如果任何人拥有您的 public 密钥,他们都可以验证您的签名,但没有其他人可以签署它。
术语会令人困惑。有 4 个 RSA 操作,最好描述为:签名、验证、加密、解密。将这些映射到较低级别并仅使用加密和解密的语言,这些映射如下:
签名验证对
- 签名 -> 使用私钥加密
- 验证 -> 使用 public 密钥解密
加密-解密对
- 正在加密 -> 使用 public 密钥加密
- 解密 -> 用私钥解密。
如您所见,每一对操作的一侧都有私钥,另一侧有 public 密钥。