Javajava.security.Signatureクラスが何をするのかを理解しようとしています。SHA1メッセージダイジェストを計算し、RSAを使用してそのダイジェストを暗号化すると、Signatureクラスに同じものに署名するように要求した場合とは異なる結果が得られます。
// Generate new key
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
String plaintext = "This is the message being signed";
// Compute signature
Signature instance = Signature.getInstance("SHA1withRSA");
instance.initSign(privateKey);
instance.update((plaintext).getBytes());
byte[] signature = instance.sign();
// Compute digest
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
byte[] digest = sha1.digest((plaintext).getBytes());
// Encrypt digest
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] cipherText = cipher.doFinal(digest);
// Display results
System.out.println("Input data: " + plaintext);
System.out.println("Digest: " + bytes2String(digest));
System.out.println("Cipher text: " + bytes2String(cipherText));
System.out.println("Signature: " + bytes2String(signature));
結果(例):
入力データ:これは署名されているメッセージです
ダイジェスト:62b0a9ef15461c82766fb5bdaae9edbe4ac2e067
暗号文:057dc0d2f7f54acc95d3cf5cba9f944619394711003bdd12 ...
署名:7177c74bbbb871cc0af92e30d2808ebae146f25d3
私はSignatureが何をしているのかについて根本的な誤解を持っている必要があります-私はそれをトレースしました、そしてそれは私が期待するようにアルゴリズムがSHA1に設定されたMessageDigestオブジェクトでupdateを呼び出しているようです、そしてダイジェストを取得し、そして暗号化。結果が異なる理由は何ですか?
編集:
Leonidasは、署名スキームが私が思うことを実行することになっているのかどうかを確認させてくれました。RFCで定義されている署名には2つのタイプがあります。
これらの最初のもの(PKCS1)は、私が上で説明したものです。ハッシュ関数を使用してダイジェストを作成し、結果を秘密鍵で暗号化します。
2番目のアルゴリズムはランダムなソルト値を使用し、より安全ですが決定論的ではありません。上記のコードから生成された署名は、同じキーを繰り返し使用しても変更されないため、PSSではないと思います。
編集:
これが私が使っていたbytes2string
方法です:
private static String bytes2String(byte[] bytes) {
StringBuilder string = new StringBuilder();
for (byte b : bytes) {
String hexString = Integer.toHexString(0x00FF & b);
string.append(hexString.length() == 1 ? "0" + hexString : hexString);
}
return string.toString();
}