0

ObjectiveC で文字列に署名し、生成された署名を PHP で検証しています。

ObjectiveC の RSA_sign メソッド (OpenSSL Lib) で privateKey を使用して、文字列 "b1be1970fa802f43cdfa382bb3f3a524590b2170" に署名するとします。そして、生成された署名を取得します

openssl_verify メソッドで PublicKey を使用して、PHP で署名を検証します。

検証失敗

何が間違っているのでしょうか..

iOS コード:

NSString *handshakeChallengeStr = [NSString stringWithFormat:@"YjFiZTE5NzBmYTgwMmY0M2NkZmEzODJiYjNmM2E1MjQ1OTBiMjE3MA=="];
NSData *hcData = [NSData dataFromBase64String:handshakeChallengeStr];
const unsigned char *message = (const unsigned char *)[hcData bytes];
unsigned int message_length =strlen((const void *)message); //56

unsigned char *sig = NULL;
unsigned int sig_len = 0;

//Retriving PrivateKey
RSA *privKey = NULL;
EVP_PKEY *PrivateKey;
FILE *priv_key_file;
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES);
NSString *keyFilePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:@"privateKey.pem"];

priv_key_file = fopen([keyFilePath UTF8String], "r");
PrivateKey = PEM_read_PrivateKey(priv_key_file, NULL, NULL, NULL);
privKey = EVP_PKEY_get1_RSA(PrivateKey);

sig = malloc(RSA_size(privKey));

int success = RSA_sign(NID_sha1, message, message_length, sig, &sig_len, privKey);
if(success == 1){
    NSLog(@"Signature Generated!!");
}

PHP コード:

$private = '-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDZz+ztvFV3qYu8
4NHErDVfVzfVhAVoCqQiCFBWpuNJk0xPgGIkwDkehhyIxCT1CD/GNYQSjpoFlfId
….
-----END PRIVATE KEY-----';

$public='-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2c/s7bxVd6mLvODRxKw1
X1c31YQFaAqkIghQVqbjSZNMT4BiJMA5HoYciMQk9Qg/xjWEEo6aBZXyHekc7w1d
……
-----END PUBLIC KEY-----';

$HandshakeStr = base64_decode('YjFiZTE5NzBmYTgwMmY0M2NkZmEzODJiYjNmM2E1MjQ1OTBiMjE3MA==');;

openssl_sign($HandshakeStr, $sig, $private);
4

2 に答える 2

2

PHPは、ハッシュに SHA1 を使用しopenssl_signて、指定されたデータの署名を計算します( PHP: openssl_sign )。

OpenSSL RSA_signは、サイズ m_lenのメッセージ ダイジェストm に署名します ( OpenSSL: RSA_sign(3) ) 。

生の OpenSSL 関数を使用する場合は、自分でハッシュを行う必要があります。

    unsigned char message_digest[SHA_DIGEST_LENGTH];
    SHA1(message, message_length, message_digest);
    int success = RSA_sign(NID_sha1, message_digest, SHA_DIGEST_LENGTH, sig, &sig_len, privKey);

ところで、RSA 検証を使用してください。すべての署名方式が決定論的というわけではありません。

于 2013-08-28T14:28:01.230 に答える
1

次の行を確認する必要があると思います

unsigned int message_length =strlen((const void *)message);

メッセージはバイナリ (Base64 からデコードされ、間に NULL 文字を含めることができる) であるため、strlen は正しい長さを返しません。NSData からメッセージの正確なバイト数を取得する必要があります。

私の計算によると、長さは 56 ではなく、約 42 になるはずです。Base64 では 3 ビットは 4 ビットになるため、56*3/4 は 42 になります。

ここでの目的は、base64 でデコードされたバイトの長さを取得することです。使用できます

message_length = [hcData length];

データに署名して検証する前に、データが正しくデコードされていることを確認してください。

もう 1 つの理由 さらに掘り下げる前に、署名の生成と検証を成功させるには何が必要かをまず分析しましょう。

署名の生成には以下が含まれます。

  1. 秘密鍵
  2. データ
  3. ハッシュアルゴリズム

署名を生成します。

そして検証が必要です:

  1. 公開鍵
  2. データ
  3. ハッシュアルゴリズム
  4. サイン

公開鍵は秘密鍵と一致する必要があります。そうしないと、署名の検証が成功しません。

データは同じでなければなりません。すべてのビットが同じである必要があります。

署名と検証で使用されるハッシュ アルゴリズムは同じでなければなりません。

その後、署名で生成された署名は、検証で使用された署名と同じである必要があります。

不一致があると、署名の不一致が発生します。

これは、どこが間違っているのかを見つけるのに役立つと思います。

于 2013-08-25T05:23:33.913 に答える