我需要解密从服务器接收到的一些数据,编写API的程序员将我定向到此Encrypter类,以查看他过去用于加密的内容。
现在基于该类,我发现所使用的算法是AES128 CBC,并且我接收到的字符串是Base64编码的,并且包含其他数据,而不仅仅是密文。
即,如果我收到以下字符串:
eyJpdiI6InJsSzRlU3pDZTBBUVNwMzdXMjVcL0tBPT0iLCJ2YWx1ZSI6Ik5JOENsSVVWaWk2RGNhNlwvWjJNeG94UzVkclwvMGJOREQreWUyS1UzclRMND0iLCJtYWMiOiJhZTZkYjNkNGM2ZTliNmU0ZTc0MTRiNDBmMzFlZTJhNTczZWIxMjk4N2YwMjlhODA1NTIyMDEzODljNDY2OTk2In0
经过base64解码后,我得到:
{"iv":"rlK4eSzCe0AQSp37W25\/KA==","value":"NI8ClIUVii6Dca6\/Z2MxoxS5dr\/0bNDD+ye2KU3rTL4=","mac":"ae6db3d4c6e9b6e4e7414b40f31ee2a573eb12987f029a80552201389c466996"}
基于line 99
的Encrypter
类(iv = base64_decode($payload['iv']);
),I执行另一解码的base64上iv
和value
,并得到了一个iv
长度为16的那些我作为参数下面的传递函数:
public static String decrypt(String iv, String encryptedData) throws Exception {
byte[] keyValue = "zy2dEd1pKG5i3WuWbvOBolFQR84AYbvN".getBytes();
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/CBC/PKCS7Padding");
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));
byte[] decordedValue = Base64.decode(encryptedData.getBytes(), Base64.DEFAULT);
byte[] decValue = c.doFinal(decordedValue);
return new String(decValue);
}
但是我收到以下错误:
10-06 19:13:33.601 12895-12895/? W/System.err: java.security.InvalidAlgorithmParameterException: expected IV length of 16
10-06 19:13:33.601 12895-12895/? W/System.err: at com.android.org.conscrypt.OpenSSLCipher.engineInitInternal(OpenSSLCipher.java:281)
10-06 19:13:33.601 12895-12895/? W/System.err: at com.android.org.conscrypt.OpenSSLCipher.engineInit(OpenSSLCipher.java:323)
10-06 19:13:33.601 12895-12895/? W/System.err: at javax.crypto.Cipher.init(Cipher.java:751)
10-06 19:13:33.601 12895-12895/? W/System.err: at javax.crypto.Cipher.init(Cipher.java:701)
10-06 19:13:33.601 12895-12895/? W/System.err: at com.example.kushtrim.testproject.MainActivity.decrypt(MainActivity.java:62)
10-06 19:13:33.601 12895-12895/? W/System.err: at com.example.kushtrim.testproject.MainActivity.onCreate(MainActivity.java:45)
10-06 19:13:33.601 12895-12895/? W/System.err: at android.app.Activity.performCreate(Activity.java:5990)
10-06 19:13:33.601 12895-12895/? W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
10-06 19:13:33.601 12895-12895/? W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
10-06 19:13:33.601 12895-12895/? W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
10-06 19:13:33.601 12895-12895/? W/System.err: at android.app.ActivityThread.access$800(ActivityThread.java:151)
10-06 19:13:33.601 12895-12895/? W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
10-06 19:13:33.602 12895-12895/? W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
10-06 19:13:33.602 12895-12895/? W/System.err: at android.os.Looper.loop(Looper.java:135)
10-06 19:13:33.602 12895-12895/? W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5254)
10-06 19:13:33.602 12895-12895/? W/System.err: at java.lang.reflect.Method.invoke(Native Method)
10-06 19:13:33.602 12895-12895/? W/System.err: at java.lang.reflect.Method.invoke(Method.java:372)
10-06 19:13:33.602 12895-12895/? W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
10-06 19:13:33.602 12895-12895/? W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
注意: 字符串的iv
长度为16,但iv.getBytes()
返回长度为26的数组。
有人可以指出我出了问题的地方,以及如何解决它。谢谢/
编辑
注释之后,我进行了一些更改,解决了上述错误:
在进行base64解码之前iv
,将字节转换为String,然后将该String传递给解密方法,该方法在其上调用了getBytes()。不知何故,字节数组的长度为26。 将我在base64解码后获得的字节数组发送给解密方法解决了该问题。
现在的方法如下:
public static String decrypt(byte[] iv, String encryptedData) throws Exception {
byte[] keyValue = "zy2dEd1pKG5i3WuWbvOBolFQR84AYbvN".getBytes();
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/CBC/PKCS7Padding");
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] decordedValue = Base64.decode(encryptedData.getBytes(), Base64.DEFAULT);
byte[] decValue = c.doFinal(decordedValue);
return new String(decValue);
}
现在,我又 遇到了 一个 奇怪的 问题:
首先加密的文本是KushtrimPacaj
,但是解密的文本是
s:13:"KushtrimPacaj";
。那另一部分是哪里来的呢?13也许代表长度KushtrimPacaj
?
您可以在padAndMcrypt()
函数中看到,给定的$
value是使用PHP的serialize()
function序列化的。您可以用Java
重新实现该unserialize()
功能,或者如果您始终使用PHP加密字符串,则可以自己拆分字节数组。
int firstQuoteIndex = 0;
while(decValue[firstQuoteIndex] != (byte)'"') firstQuoteIndex++;
return new String(Arrays.copyOfRange(decValue, firstQuoteIndex + 1, decValue.length-2));
完整代码:
public static String decrypt(byte[] keyValue, String ivValue, String encryptedData) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
byte[] iv = Base64.decode(ivValue.getBytes("UTF-8"), Base64.DEFAULT);
byte[] decodedValue = Base64.decode(encryptedData.getBytes("UTF-8"), Base64.DEFAULT);
Cipher c = Cipher.getInstance("AES/CBC/PKCS7Padding"); // or PKCS5Padding
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] decValue = c.doFinal(decodedValue);
int firstQuoteIndex = 0;
while(decValue[firstQuoteIndex] != (byte)'"') firstQuoteIndex++;
return new String(Arrays.copyOfRange(decValue, firstQuoteIndex + 1, decValue.length-2));
}
验证MAC始终是一个好主意,因为它可以防止某些攻击,例如padding oracle攻击。这也是检测密文的一般修改的一种非常好的方法。
具有MAC验证的完整代码:
public static String decrypt(byte[] keyValue, String ivValue, String encryptedData, String macValue) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
byte[] iv = Base64.decode(ivValue.getBytes("UTF-8"), Base64.DEFAULT);
byte[] decodedValue = Base64.decode(encryptedData.getBytes("UTF-8"), Base64.DEFAULT);
SecretKeySpec macKey = new SecretKeySpec(keyValue, "HmacSHA256");
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
hmacSha256.init(macKey);
hmacSha256.update(ivValue.getBytes("UTF-8"));
byte[] calcMac = hmacSha256.doFinal(encryptedData.getBytes("UTF-8"));
byte[] mac = Hex.decodeHex(macValue.toCharArray());
if (!secureEquals(calcMac, mac))
return null; // or throw exception
Cipher c = Cipher.getInstance("AES/CBC/PKCS7Padding"); // or PKCS5Padding
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] decValue = c.doFinal(decodedValue);
int firstQuoteIndex = 0;
while(decValue[firstQuoteIndex] != (byte)'"') firstQuoteIndex++;
return new String(Arrays.copyOfRange(decValue, firstQuoteIndex + 1, decValue.length-2));
}
/* Constant-time compare to prevent timing attacks on invalid authentication tags. */
public static boolean secureEquals(final byte[] known, final byte[] user) {
int knownLen = known.length;
int userLen = user.length;
int result = knownLen ^ userLen;
for (int i = 0; i < knownLen; i++) {
result |= known[i] ^ user[i % userLen];
}
return result == 0;
}
如果生成RSA密钥和加密文本,如下所示 现在我想在JAVA源代码中解密。有什么办法吗?
问题内容: 我编写的使用3DES在Java中对字符串进行编码的每种方法都无法解密回原始字符串。是否有人有一个简单的代码片段,可以对字符串进行编码,然后再将其解码回原始字符串? 我知道我在此代码中的某个地方犯了一个非常愚蠢的错误。到目前为止,这是我一直在努力的工作: 注意,我不是从crypto方法返回BASE64文本,也不是在解密方法中不是对base64进行未编码的,因为我试图查看我是否在BASE6
问题内容: 我需要用openssl生成的和密钥替换从Unix到Java代码的加密和解密步骤 我生成密钥 我在Unix中使用键(我需要在Java中执行) 这是我的尝试 但它不起作用,PKCS8EncodedKeySpec / X509EncodedKeySpec不正确…但是我不知道该放什么 问题答案: 我认为您在读取PEM文件时遇到问题。JPA不直接支持PEM格式。您有两种选择,要么将它们转换为DE
问题内容: 我正在尝试编写一个使用RSA密钥对加密和解密纯文本文件的实用程序。RSA密钥是使用ssh-keygen生成的,并照常存储在.ssh中。 我在理解如何使用Go语言crypto和crypto / rsa软件包时遇到问题吗?有关这些文档的文档很少(甚至更多,因为我对加密还不熟悉),并且示例很少。我检查了rsa_test.go文件是否有任何线索,但这只会使我更加困惑。 简而言之,我试图从.ss
问题内容: 很难在Google上找到直接答案。 我想从诸如的用户那里收集一段文字和一条消息 。 然后,我希望能够以某种方式对消息进行加密/解密,以便可以将其保存在数据库中,而不必担心如果我的网站被黑客入侵,数据就会被泄露, 有没有一种简单的方法可以用python实现,请有人提供/指导我看一个例子。 也许是一个示例,该示例如何使用诸如之类的种子创建公钥/私钥对? 提前谢谢了 :) 编辑:为了清楚起见
Perl脚本使用此模块加密字符串http://search.cpan.org/~zefram/Crypt-Eksblowfish-0.009/lib/Crypt/Eksblowfish.pm 我需要用python编写解密函数。我知道钥匙和盐。我试图使用py-bcrypt,但似乎两个等价函数 $ciphertext=$cipher- 没有实施。 我该怎么办?有没有python模块可以帮助我解密字符串