【问题标题】:Base64 Decode not working correctly along with Cipher.Decrypt in androidBase64 解码与 Cipher.Decrypt 在 android 中无法正常工作
【发布时间】:2012-05-19 05:14:09
【问题描述】:

这是一个字符串:

String msg="dpbqNszFN2cpmtlzPi3myV9M1ctlkSIQD95ue+T+9rz13T+Pe/aLZ8Pd5geI+PhEM/b0UeRS1cAzKybQsKICTBhh3ke5Jjw6BHWGESJWBnUT54lAlTvzkgOxpQ5stBh2cPPSn3KLyKmXifr8ClbV5s1k3Gy5C7HitA5KLw7hRxAmIGSWQG7PaiLNEVRbgicNfJ7Ic7VIdGA/UA51vK8mpywIR2YQUDPv30ThGq4DuclaJ3X4aVWVj8VYChcfM+82sViVU8HO3DF9CCU4EIADNET503olxiDZBp7WMYmJvWq0KhhZXkLSY3QFmcSMX6IThtdKKCcZp6hu3TtC+7aP7Q==";

所以字节数组是

[1] => 100     [2] => 112     [3] => 98     [4] => 113     [5] => 78     [6] => 115     [7] => 122 ..

应该解码成

[我使用 PHP base64_encode() 编码为上述形式,base64_decode() 用于获取此输出]

[1] => 118     [2] => 150     [3] => 234     [4] => 54     [5] => 204     [6] => 197      7] => 55     ...

但我面临的问题是(在 android 中,使用 Base64.decode(String))它被解码为:

[118, -106, -22, 54, -52, -59, 55, 103, 41, -102, -39, 115, 62, 45, -26, -55, 95, 76, -43, -53, 101, -111, 34, 16, 15, -34, 110, 123, -28, -2, -10, -68, -11, -35, 63, -113, 123, -10, -117, 103, -61, -35, -26, 7, -120, -8, -8, 68, 51, -10, -12, 81, -28, 82, -43, -64, 51, 43, 38, -48, -80, -94, 2, 76, 24, 97, -34, 71, -71, 38, 60, 58, 4, 117, -122, 17, 34, 86, 6, 117, 19, -25, -119, 64, -107, 59, -13, -110, 3, -79, -91, 14, 108, -76, 24, 118, 112, -13, -46, -97, 114, -117, -56, -87, -105, -119, -6, -4, 10, 86, -43, -26, -51, 100, -36, 108, -71, 11, -79, -30, -76, 14, 74, 47, 14, -31, 71, 16, 38, 32, 100, -106, 64, 110, -49, 106, 34, -51, 17, 84, 91, -126, 39, 13, 124, -98, -56, 115, -75, 72, 116, 96, 63, 80, 14, 117, -68, -81, 38, -89, 44, 8, 71, 102, 16, 80, 51, -17, -33, 68, -31, 26, -82, 3, -71, -55, 90, 39, 117, -8, 105, 85, -107, -113, -59, 88, 10, 23, 31, 51, -17, 54, -79, 88, -107, 83, -63, -50, -36, 49, 125, 8, 37, 56, 16, -128, 3, 52, 68, -7, -45, 122, 37, -58, 32, -39, 6, -98, -42, 49, -119, -119, -67, 106, -76, 42, 24, 89, 94, 66, -46, 99, 116, 5, -103, -60, -116, 95, -94, 19, -122, -41, 74, 40, 39, 25, -89, -88, 110, -35, 59, 66, -5, -74, -113, -19]

如您所见,某些字符(虽然不可读)没有被正确解码。 Edit(2) :字节在 java 中有符号,在 PHP 中是无符号的。感谢@Jon 和@Tony 清除了这个想法。但是这个错误仍然存​​在于我的代码中。

编辑(1):

代码段:

KeyFactory fact = KeyFactory.getInstance("RSA");
BigInteger e=new BigInteger("65537");
BigInteger n=new BigInteger("B7AC0C8F738305F8BDDF93EE25655A70FBDF9F074640C159E36914C227BE1E50A615A25E6706EBA08FB79216F02279420ED4C9DA310778601F6A3233EDADE2FF3775D29E5302C4FCB9E7879D9F3C814AE8F42759148D91CDB23E528241AE2E44F6DE9D4334494C103886B2333D5833EFEABD76205B8F4897BB908E71697A10F6494EBFB0392A831575F64672E0F915A88F46F7FC03E7F94EB56A8A3296840095CB53787EE6E71D4C297108EA5CDD31BD37B1C0A55A8B5FA78F88FC82AEF3C2C80C0FC2CC97A1AEC74ACE44F4AC1B111B727311DA4D1447899A15BA292BCA4E7E864DF55CCB903CD4109874AD475393E7F24FC60E2D7B88E9B4FB57FA54A9B817",16);
RSAPublicKeySpec keySpec=new RSAPublicKeySpec(n,e);
PublicKey pubKey = (PublicKey) fact.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pubKey );
String msg="dpbqNszFN2cpmtlzPi3myV9M1ctlkSIQD95ue+T+9rz13T+Pe/aLZ8Pd5geI+PhEM/b0UeRS1cAzKybQsKICTBhh3ke5Jjw6BHWGESJWBnUT54lAlTvzkgOxpQ5stBh2cPPSn3KLyKmXifr8ClbV5s1k3Gy5C7HitA5KLw7hRxAmIGSWQG7PaiLNEVRbgicNfJ7Ic7VIdGA/UA51vK8mpywIR2YQUDPv30ThGq4DuclaJ3X4aVWVj8VYChcfM+82sViVU8HO3DF9CCU4EIADNET503olxiDZBp7WMYmJvWq0KhhZXkLSY3QFmcSMX6IThtdKKCcZp6hu3TtC+7aP7Q==";
byte[] bytes=msg.getBytes("UTF-8");
byte[] enc_bytes= Base64.decode(bytes,Base64.DEFAULT);
byte[]  dt = cipher.doFinal(enc_bytes);   
String code=new String(dt,"UTF-8");
System.out.println(code);

密码解密后的字符串为(在第二个 system.out 处)

05-10 21:05:27.501: I/System.out(11809): �ќ2`��H&��'Va�x�m��0G�����V�T�����)^����/|���BG,f_r    fK�B7?�a��n������Jl�y�yL���}��΂Ճ������JZj�+�|�-#ș%u�1�z�c�G��nl�5����HELLO HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 H

Base64_encoded & 签名数据是“HELLO HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 HI1 H”


[已解决]

非常感谢@JonSkeet。

cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 删除了所有以它为前缀的垃圾数据。

【问题讨论】:

  • 验证 PHP 使用与 Android 相同的算法。
  • Base64 是通用的。它应该是。对吧?
  • 我不会这么认为。检查起来很容易。但我认为你的问题已经解决了。

标签: java php android base64


【解决方案1】:

在你的字节数组上试试这个

byte[] bytes = Base64.decode(data, Base64.DEFAULT);
String string = new String(bytes, "UTF-8");

【讨论】:

  • 绝对不是。除非您有任何证据表明这实际上是 UTF-8 编码的文本(我在问题中没有看到这样的证据),否则您不应该尝试从中创建文本。
  • 答案完全无关。
  • 我的建议是基于上一个问题,当时没有添加表示数据正在加密的代码。自从我给出答案以来,对该问题进行了 2 次编辑。我不会为了创建文本而尝试创建文本。在点击发送按钮之前,人们应该仔细阅读他们的代码段。
【解决方案2】:

在我看来一切都很好——你只需要记住字节是用 Java 签名的。因此,Java 中的值 -106 对应于无符号值 150。一旦记住这一点,我想您会发现 PHP 中的所有值都对应于 Java 中的值。

请注意,您应该区分字节字符。所以当你说:

如您所见,某些字符(虽然不可读)未正确解码。

实际上是指一些字节......并且没有“可读”字节这样的概念。

编辑:我没有看到任何迹象表明您实际上已经解密了数据。

您正在使用平台默认编码将base64解码的仍然加密结果转换为文本:

String tmpr=new String(baser);

您不应该这样做 - 您应该使用 baser 作为密文来解密。

根本不清楚您传递给doFinaltmp 值来自哪里...

【讨论】:

  • 我的意思是,Base64 编码的数据不是可读的字符串。这是一个加密数据。
  • @ngen:如果问题出在解密(正如您稍后在评论中添加的那样),那么这表明问题出在加密或解密代码上,您没有向我们展示。 base64 部分在这里似乎很好。但重要的是要了解解码后的 base64 根本不是 string,可读或不可读 - 它只是字节。
  • 也许他的意思是它是加密的,然后是 BASE-64'd?
  • @TonyEnnis:是的,看到另一个有意义的评论。但是将解码后的数据完全称为“字符串”仍然是错误的。
  • @ngen:啊 - 在那种情况下,它很可能只是涉及到 CBC/填充模式(或初始化向量等)。您应该对此进行调查。
【解决方案3】:

您的问题是标志之一。第一个样本“应该”将输出字节视为 8 位无符号。 Android 版本将它们视为有符号字节。

你的代码真的失败了吗?

编辑

cipher.final() 似乎是为了完成解密而设计的。你先打电话给cipher.update()了吗?请参阅此处的示例,并查找 update(...)stackoverflow.com/questions/3150830/android-encryption

这里是Android Cipher documentation,为了您的方便。

【讨论】:

  • 是的,当“签名”字节数组进入密码解密时失败。
  • 解密期望什么输入类型?如果它需要一个无符号数组,您可能必须将字节数组转换为无符号数组。
  • 这是 Android 的 Cipher.doFinal(byte[]) 。它期待字节。但它无法解密数据,并且在实际数据前面添加了很多垃圾。
  • 我认为是 Cipher.doFinal(byte[])
  • 我对这个错误完全感到困惑,对不起。我会更清楚和具体。 Cipher.doFinal() 接受字节数组,我正在正确尝试,它甚至在解密。但是我在编辑中提到的问题是,它会产生 Illegible string 。我现在假设是由于有符号/无符号字节吗? Java 只支持有符号字节?。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-15
相关资源
最近更新 更多