0

以下に、SHA1 を使用してメッセージのハッシュを作成し、ハッシュを出力し、RSA アルゴリズムを使用してメッセージを暗号化し、暗号化されたメッセージを出力し、メッセージを復号化してハッシュを再度出力するコードをいくつか示します。最初と 3 番目の印刷メッセージは、どちらも元のメッセージの暗号化されていないハッシュであるため、一致するはずですが、私のコードでは一致しません。理由を教えてもらえますか? ありがとう。私のコードは次のとおりです。

    String          input = "input message test";
    MessageDigest   hash = MessageDigest.getInstance("SHA1");

    hash.update(Utils.toByteArray(input));

    System.out.println("digest : " +hash.digest());

    Cipher           cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    SecureRandom     random = new SecureRandom();

    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");

    generator.initialize(512, random);

    KeyPair          pair = generator.generateKeyPair();
    Key              pubKey = pair.getPublic();
    Key              privKey = pair.getPrivate();

    cipher.init(Cipher.ENCRYPT_MODE, privKey);

    byte[] ciphertext = cipher.doFinal(hash.digest());

    System.out.println("cipher: " + ciphertext);

    cipher.init(Cipher.DECRYPT_MODE, pubKey);

    byte[] plaintext = cipher.doFinal(ciphertext);

    System.out.println("plaintext : " + plaintext);

更新: 私はすでにこれを持っています.2番目のファイルにあったので削除しました. 私の方法は次のとおりです。

    public static String toHex(byte[] data, int length) {
    StringBuffer buf = new StringBuffer();

    for (int i = 0; i != length; i++) {
        int v = data[i] & 0xff;

        buf.append(digits.charAt(v >> 4));
        buf.append(digits.charAt(v & 0xf));
    }

    return buf.toString();
}

しかし、これは次を返します:

digest : b2cad21e87dbd57f1a1928e4013b56fb553bb82a
cipher: 502cffa545bda39f677b72f677f1a6a4308a329747a8f4de9b0d1ffd83fcec10c5b41a218201e204c7949b45a8119eb42e6ab5dc0c97f97b6d59600632d2b2ad
plaintext : da39a3ee5e6b4b0d3255bfef95601890afd80709
4

1 に答える 1

2

ハッシュ ダイジェストは 1 回だけ実行する必要があります (ドキュメントを参照)。

System.out.println("digest : " + hash.digest());   //1
byte[] ciphertext = cipher.doFinal(hash.digest()); //2

一度呼び出すhash.digest()と、ダイジェストが作成され、ハッシュ オブジェクトがリセットされます。これが、異なる出力が得られる理由です。

以下は私が行った変更です:

 byte[] inputHash = hash.digest();
 System.out.println("digest : " + bytesToHex(inputHash));
 byte[] ciphertext = cipher.doFinal(inputHash);

これが私が得る出力です:

digest    : 4b03b72ccc3b238e3df3c0a9dcb8d03fd6417848
plaintext : 4b03b72ccc3b238e3df3c0a9dcb8d03fd6417848

16 進数に変換された任意のバイト配列を使用できます。以下は、使用できるスニペットです。

public static String bytesToHex(byte[] hash) {
    StringBuffer hexString = new StringBuffer();

    for (int i = 0; i < hash.length; i++) {
      String hex = Integer.toHexString(0xff & hash[i]);
      if(hex.length() == 1) hexString.append('0');
      hexString.append(hex);
    }

    return hexString.toString();
  }
于 2014-12-07T11:05:01.417 に答える