0

私は、apache wicket によって構築された単純な Java Web アプリケーションを持っています。Web アプリでユーザーを登録するとき、ユーザーが入力するパスワードをトリプルを使用して暗号化し、データベースに保存します。彼らが同じパスワードを入力したときのログインページで、それを暗号化し、暗号化されたパスワードをデータベースに渡して、それが正しいかどうかを確認します。

現在、同じログイン機能を持つAndroidアプリの構築に取り組んでいます。

Android アプリのログイン ページでは、パスワードの暗号化に同じ暗号化ライブラリを使用しており、両方のプラットフォームで同じキーと初期化ベクトルを使用していますが、Android で同じパスワード文字列を入力しようとすると、TripleDes アルゴリズムはまったく異なる暗号化パスワードを生成します (多くのより長いです)。したがって、Android デバイスからのログインは失敗します。また、Android が生成する暗号化されたパスワードは復号化できず、例外がスローされることに気付きました。

2 つのプラットフォーム間で文字列エンコーディングの問題に違いがあるのではないかと考えていますが、その原因と修正方法がわかりません。

私が使用するアルゴリズムは次のとおりです。

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

}

4

1 に答える 1

2

(編集:前述のように、パスワードを可逆的に保存することは最初から悪い考えですが、暗号化の部分を正しくするために...)

最初の問題は次のとおりです。

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

これは、デフォルトのシステム文字エンコーディングを使用しています。すべての Android フォンで同じですか?知らない。Android でも Web サーバーと同じですか? 知らない。あるプラットフォームが UTF-16 を使用し、別のプラットフォームが UTF-8 を使用しplainText、すべてが ASCII である場合、暗号化されたデータのサイズに 2 倍の違いがあることは確かです。

常にエンコーディングを指定することをお勧めします。多くの場合、「UTF-8」が適切な選択です。

編集:さて、問題は後であなたがしたことでもあっcipherTextたようです。生のバイトを base64 文字列に変換する必要があります。Android には base64 エンコーダーが組み込まれていますが、このパブリック ドメイン コードは正常に動作するはずです。この行の代わりに:

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

あなたが使うだろう

return Base64.encodeBytes(cipherText);
于 2011-09-27T16:58:46.717 に答える