Java 当从android调用TripleDES算法时,会产生不同的结果

Java 当从android调用TripleDES算法时,会产生不同的结果,java,android,encoding,tripledes,Java,Android,Encoding,Tripledes,我有一个简单的JavaWeb应用程序,它是由ApacheWicket构建的。当我在web应用程序中注册用户时,我使用tripledes加密用户输入的密码并将其保存到数据库中。在登录页面中,当他们输入相同的密码时,我对其进行加密并将加密的密码传递给db,以检查其是否正确 现在我正在构建一个android应用程序,它将具有相同的登录功能 在android应用程序登录页面中,我使用相同的加密库来加密密码,两个平台使用相同的密钥和初始化向量,但如果我尝试在android中输入相同的密码字符串,Tripl

我有一个简单的JavaWeb应用程序,它是由ApacheWicket构建的。当我在web应用程序中注册用户时,我使用tripledes加密用户输入的密码并将其保存到数据库中。在登录页面中,当他们输入相同的密码时,我对其进行加密并将加密的密码传递给db,以检查其是否正确

现在我正在构建一个android应用程序,它将具有相同的登录功能

在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);
    }
}

(编辑:如前所述,以可逆方式存储密码一开始是一个坏主意,但为了正确使用加密部分…)

这是第一个问题:

byte[] plaintext = plainText.getBytes();
byte[] tdesKeyData = key.getBytes();
这是使用默认的系统字符编码。在所有安卓手机上都是一样的吗?我不知道。Android和web服务器上的相同吗?我不知道。如果一个平台使用UTF-16,另一个平台使用UTF-8,并且
明文
都是ASCII码,那么这肯定会解释加密数据大小差异的两个因素

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

编辑:好的,问题似乎也是你后来用
密文所做的。您需要将原始字节转换为base64字符串。安卓系统内置了base64编码器,但可以正常工作。而不是这一行:

return Base64Coder.encodeString(new String(cipherText));
你会用

return Base64.encodeBytes(cipherText);

我已经试过了,但没用,它仍然生成了同样错误的加密密码。@user967505:好吧,你还是应该首先解决这个问题。。。然后你至少可以检查你是否有相同的明文和密钥数据。我检查了两个应用程序的默认字符集,一个是windows-1252,另一个(android)是UTF-8,所以这肯定是问题1,现在我使用UTF-8在加密算法中获取字节。获取字节后,我记录了两个应用程序的字节总数和两个数组的长度,但它们似乎匹配。@user967505:对,这是一个问题。那么,
初始化向量如何呢?现在两个平台上的加密大小是否相同?是的,初始化向量相同。我刚把它们打印出来。不幸的是,我仍然看到加密文本之间的大小差异。为什么要使用可逆加密存储用户密码?这通常是错误的身份验证方法。我只有一种加密方法,需要对其他一些敏感数据进行可逆加密。我想我应该使用一些不可逆的东西,比如MD5来进行密码加密。如果你的“密钥”实际上是一个密码(文本),那么你应该从中派生一个密钥,而不是直接将它用作加密密钥。一个好的密钥派生算法,如PBKDF2,也可以实现一个好的单向身份验证功能。谢谢,我会记住这一点,但我仍然需要启动并运行它,因为我需要在我的应用程序中对其他屏幕进行可逆加密。