我在ObjectiveC中签名一个字符串,并在PHP中验证生成的签名。
假设我在ObjectiveC中使用带有RSA_sign方法(OpenSSL Lib)的privateKey签署字符串“b1be1970fa802f43cdfa382bb3f3a524590b2170”。 我得到了生成的签名
我使用PublicKey和openssl_verify方法在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);
答案 0 :(得分:2)
PHP openssl_sign
通过使用SHA1进行散列(PHP: openssl_sign)来计算指定数据的签名。
OpenSSL RSA_sign 签署消息摘要 m,大小为m_len(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验证 - 并非每个签名方案都是确定性的。
答案 1 :(得分:1)
我认为你应该检查以下一行
unsigned int message_length = strlen((const void *)message);
由于消息是二进制的(它是从Base64解码的,并且中间可以包含NULL字符),因此strlen不会返回正确的长度。您应该从NSData获得消息中的确切字节数。
根据我的计算,长度不应该是56但是大约为42.由于3位在Base64中占4位,因此56 * 3/4达到42位。
这里,您的目的是获得base64解码字节的长度。你可以使用
message_length = [hcData length];
在签署数据并进行验证之前,请检查数据是否已正确解码。
另一个原因 在深入研究之前,让我们先分析一下将使签名生成和验证成功的原因。
签名生成涉及:
它会生成一个签名。
验证需求:
公钥应与私钥匹配。否则,签名验证将不会成功。
数据必须相同。每一点都应该相同。
签名和验证中使用的哈希算法必须相同。
之后,签名中生成的签名应与验证中使用的签名相同。
任何不匹配都会导致签名不匹配。
我相信这可以帮助你找出问题所在。