9

私は Android アプリを開発しており、データ認証にJavaSignatureクラスを使用する必要があります。

各 Android デバイスで、データに署名し、その署名を検証できます。ただし、署名するデータの明確なチャンク、明確なモジュラス、明確なプライベート指数、および明確なパブリック指数が与えられた場合、署名の出力はデバイスによって異なります。私はたくさんのデバイスで試してみましたが、Android 3.2 と 3.2.1 で同じ署名を取得しましたが、Android 2.2.x デバイスでは違いました。

KeyFactoryJava プロジェクトで RSAを使用して以前に生成した定数フィールドからこれらの署名を計算します。キーサイズは 2048bit です。

以下は、署名と検証を呼び出すために使用するコードの引用です。

public byte[] signData(byte[] data, PrivateKey privateKey) throws ... {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
}

public boolean verifyData(byte[] data, byte[] sigBytes, PublicKey publicKey) throws ... {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(sigBytes);
}

間違いでなければ、RSA で SHA256 を使用した署名は確定的です。では、そのような行動をどのように説明できますか?もう 1 つの興味深い質問は、デバイスをまたがって機能させるにはどうすればよいかということです。

前もってありがとう、フランク!

4

1 に答える 1

12

はい、SHA256withRSA完全に決定論的です。

理論的には、Androidバージョンの1つにある古い変更されたBouncyCastleライブラリバージョンのバグ(例を参照)の影響を受ける可能性があります。代わりに使用すれば、このようなバグは解消される可能性がありSHA512withRSAます。少なくとも参照されているバグは解消されます。

ただし、ハッシュアルゴリズムを掘り下げる前に、家の近くを確認してください。

の呼び出しを通じてバイト配列を取得した可能性がありますString.getBytes。この呼び出しは、Android2.2とAndroid2.3で異なるデフォルトのプラットフォームエンコーディングに依存します。これは、どちらの場合も文字列は同じですが、バイト配列は同じではない可能性があることを意味します。

エンコーディングを制御し、コードプラットフォームを独立させるには、パラメータとしてエンコーディングを指定します。

plainText.getBytes("UTF-8")

これに失敗すると、プラットフォームに依存しない実装を取得するための戦術がさらにいくつかあります。

  • おそらくバグのあるライブラリがなくなるまで2.2まで待つ
  • 既知の良好なライブラリ(jar)をソフトウェアと一緒に配布します。それがBouncyCastleの場合、Androidのクラスではなく自分のクラスがロードされていることを確認する際に問題が発生します。このソリューションはSpongyCastleと呼ばれます。
  • アラインメント/パディングで遊んでください。独自の固定パディングを追加して、64を法とする0、55、56、または63と一致するように、バイト単位のメッセージ長を作成し、これらのオプションの1つがポータブル署名の提供を開始することを期待してください。これらの値は、512ビットブロックにパディングされている疑わしいアルゴリズムの最も外側の部分と相互作用するように選択されます。
于 2012-06-28T21:14:53.710 に答える