3

SHA-1 ダイジェスト (20 バイト) に署名するために使用したい 256 ビットの秘密鍵があります。openssl を直接使用するとうまくいくようです

エコーは関係ありません | openssl dgst -sha1 -バイナリ | openssl rsautl -sign -inkey 256bit_private_key.pem | openssl enc -base64

期待どおりのBase64出力が得られます。

しかし、OpenSSL でそれを行うと、「error:04075070:rsa routines:RSA_sign:digest too big for rsa key」で失敗します。以下に示すように、RSA_sign への入力として 20 バイト (SHA_DIGEST_LENGTH=20) の SHA-1 ダイジェストを渡しています。パディングがあっても、256 ビットのモジュラス キーで暗号化できる最大 32 バイトを超えてはなりませんか?!

unsigned char digest[SHA_DIGEST_LENGTH];
SHA1(message, messageSize, digest);

unsigned int privateKeySize = RSA_size(privateKey); // 256 bits = 32 bytes
unsigned char* signature = new unsigned char[privateKeySize];
unsigned int signatureSize;

int res = RSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH, signature, &signatureSize, privateKey);

if(res == 0)
{
    int err = ERR_get_error(); // 67588208
    char *s = ERR_error_string(err, 0); // error:04075070:lib(4):func(117):reason(112)

    delete [] signature;

    [...]
}

コードで何が間違っていますか?

4

3 に答える 3

3

ピーター・エリオット氏: そうではありません。

RFC8017 セクション 8.2.1 (および 9.2、rfc4347 と rfc3447 と同様)の PKCS1v1_5 標準シーケンスはハッシュであり、ASN.1 でエンコードされ、パッド (「タイプ 1」) および modexp d です。(PSS は ASN.1 ステップを省略し、異なるパディングを使用します。)

OpenSSL (低レベル)RSA_signは最後の 3 つ (v1.5 パディングあり) を実行しますが、最初の 3 つを実行しません。つまり、ハッシュをエンコードしますが、ハッシュは実行しません。even-lowerRSA_private_encryptは最後の 2 つを行います。上位レベルのエンベロープ モジュール (オリジナルEVP_Sign{Init,Update,Final}*、拡張EVP_DigestSign*) は、4 つすべてを実行します。256 ビット キーに対して値が大きすぎるのは ASN.1 エンコードです。

rsautlエンコードではなく最後の 2 つのステップのみを実行するため、実行されますが、標準的でない結果が得られます。 pkeyutlRSA はデフォルトで同じことを行いますが、エンコードを行うように指示できます。

また、PSS はより優れたセキュリティ証明を持っていますが、私が聞いた限りでは、v1.5 に対する実際の攻撃はなく、まだ広く使用されています。PSS を選択できる場合 (両方/すべての関係者がサポート)、それを選択しますが、v1.5 を使用することについて心配する必要はありません。

于 2013-10-10T20:55:18.357 に答える
3

check out this SO answer. rsautl is depreciated in favor of pkeyutl

Essentially, RSA signing should use RSA-PSS signature padding scheme to be secure, and the RSA-PSS will be strictly larger than the digest, because of the necessity to communicate a salt. additionally, RSA_sign does a digest as a part of the signing scheme, so your code is going to do a digest of a digest. you want to instead either pass the message in directly, or use RSA_private_encrypt combined with a suitable RSA_padding_add_x call.

and as I said in my comment, a 256-bit key is sufficiently secure for a symmetric algorithm, but it will be trivial to crack for an RSA private key (on the order of 4 minutes on a couple of year old machine). Using a bare minimum of a 1024 bit key (and probably a 2048 or 4096 bit key) will give you a security level roughly equivalent to a 128 bit symmetric algorithm.

于 2013-02-26T18:58:01.557 に答える
1

解決策を見つけたと思います。代わりにopenssl rsautl -sign使用します(私が期待していたもの)。私が提供した 20 バイトのメッセージよりも長い構造を作成するため、指定されたエラーで失敗します。RSA_private_encryptRSA_signRSA_sign

于 2013-02-26T15:18:02.013 に答える