【问题标题】:TripleDES algorithm generates different outcome when called from android从 android 调用时,TripleDES 算法会产生不同的结果
【发布时间】:2011-09-27 16:51:04
【问题描述】:

我有一个由 apache wicket 构建的简单 Java Web 应用程序。当我在网络应用程序中注册用户时,我使用三元组加密他们输入的密码并将其保存到数据库中。在登录页面,当他们输入相同的密码时,我将其加密并将加密后的密码传递给数据库,以检查它是否正确。

现在我正在构建一个具有相同登录功能的安卓应用。

在 android 应用程序登录页面中,我使用相同的加密库来加密密码,并且我对两个平台使用相同的密钥和初始化向量,但是如果我尝试在 android 中输入相同的密码字符串,TripleDes 算法会生成完全不同的加密密码(更长)。因此从 android 设备登录失败。我还注意到android生成的加密密码无法解密,它会抛出异常。

我认为两个平台之间可能存在字符串编码问题差异,但无法弄清楚是什么原因造成的以及如何解决。

这是我使用的算法:

public class TripleDES {
private String key;
private byte[] initializationVector;

public TripleDES(String key, byte[] initializationVector)
{
    this.key = key;
    this.initializationVector = initializationVector;
}

public String encryptText(String plainText) throws Exception{
//----  Use specified 3DES key and IV from other source -------------------------
  byte[] plaintext = plainText.getBytes();
  byte[] tdesKeyData = key.getBytes();

  System.out.println("plain text length: " + plaintext.length);
  System.out.println("key length: " + tdesKeyData.length);


  Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
  SecretKeySpec    myKey = new SecretKeySpec(tdesKeyData, "DESede");
  IvParameterSpec ivspec = new IvParameterSpec(initializationVector);

  c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec);
  byte[] cipherText = c3des.doFinal(plaintext);

  return Base64Coder.encodeString(new String(cipherText));
}

public String decryptText(String encryptedText) throws Exception{
    //----  Use specified 3DES key and IV from other source -------------------
      byte[] enctext = Base64Coder.decode(encryptedText);
      byte[] tdesKeyData = key.getBytes();


      Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
      SecretKeySpec    myKey = new SecretKeySpec(tdesKeyData, "DESede");
      IvParameterSpec ivspec = new IvParameterSpec(initializationVector);

      c3des.init(Cipher.DECRYPT_MODE, myKey, ivspec);
      byte[] cipherText = c3des.doFinal(enctext);
      return new String(cipherText);
    }

}

【问题讨论】:

  • 为什么要使用可逆加密存储用户密码?这通常是进行身份验证的错误方法。
  • 我只有一种加密方法,我需要对其他一些敏感数据进行可逆加密。我想我应该使用像 MD5 这样不可逆的密码加密。
  • 如果您的“密钥”实际上是密码(文本),那么您应该从中派生密钥,而不是直接将其用作加密密钥。像 PBKDF2 这样好的密钥派生算法也可以提供好的单向认证功能。
  • 谢谢,我会记住这一点,但我仍然需要启动并运行它,因为我需要在我的应用程序中为其他一些屏幕进行一些可逆加密。

标签: java android encoding tripledes


【解决方案1】:

(编辑:如前所述,可逆地存储密码是一个坏主意,但为了正确加密部分......)

这是第一个问题:

byte[] plaintext = plainText.getBytes();
byte[] tdesKeyData = key.getBytes();

这是使用默认的系统字符编码。所有安卓手机都一样吗?我不知道。它在 Android 中与在您的 Web 服务器上是否相同?我不知道。如果一个平台使用 UTF-16 而另一个平台使用 UTF-8 并且plainText 都是 ASCII,那肯定会导致加密数据大小的两倍。

我会建议始终指定编码 - “UTF-8”在许多情况下是一个不错的选择。

编辑:好的,看起来问题是也是你后来对cipherText 所做的事情。您需要将 原始字节 转换为 base64 字符串。 Android 内置了一个 base64 编码器,但 this public domain code 应该可以正常工作。而不是这一行:

return Base64Coder.encodeString(new String(cipherText));

你会使用

return Base64.encodeBytes(cipherText);

【讨论】:

  • 我已经尝试过了,但没有帮助,它仍然生成相同的错误加密密码。
  • @user967505:嗯,你还是应该先解决这个问题……然后你至少可以检查一下你是否有相同的明文和关键数据。
  • 我检查了两个应用程序的默认字符集,一个是 windows-1252,另一个(andorid)是 UTF-8,所以这绝对是第 1 个问题,现在我使用 UTF-8 来获取加密算法中的字节。获得字节后,我记录了两个应用程序的字节总和和两个数组的长度,但它们似乎匹配。
  • @user967505:是的,这是一个问题。那么,initializationVector 呢?现在两个平台上的加密大小是否相同?
  • 是的,初始化向量是相同的。我只是把它们打印出来。不幸的是,我仍然看到加密文本之间的大小差异。
猜你喜欢
  • 2011-01-28
  • 1970-01-01
  • 2021-03-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
  • 2016-02-19
相关资源
最近更新 更多