I am signing a string in ObjectiveC and verifying the generated signature in PHP.
lets say I sign a string "b1be1970fa802f43cdfa382bb3f3a524590b2170" using my privateKey with RSA_sign method (OpenSSL Lib) in ObjectiveC. And I get generated signature
I verify the signature in PHP using PublicKey with openssl_verify method.
Verification Fails
Any idea what might be wrong..
iOS Code:
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 Code:
$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);
PHP openssl_sign
computes a signature for the specified data by using SHA1 for hashing (PHP: openssl_sign).
OpenSSL RSA_sign signs the message digest m of size m_len (OpenSSL: RSA_sign(3))
When you use the raw OpenSSL functions you have to do the hashing yourself:
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);
By the way, use RSA verify - not every signature scheme is deterministic.
I think you should check the following line
unsigned int message_length =strlen((const void *)message);
Since message is binary (it is decoded from Base64 and can contain NULL character in between), strlen will not return correct length. You should get the exact number of bytes in the message from NSData.
As per my calculation, length should not be 56 but around 42. Since 3 bits take 4 bits in Base64, 56*3/4 comes to 42.
Here, your intention is to get the length of base64 decoded bytes. You can use
message_length = [hcData length];
Before signing the data and verifying, please check that the data is decoded properly.
Another reasons Before digging into further, let us first analyze what will make signature generation and verification successful.
Signature generation involves:
It generates a signature.
And verification needs:
Public key should match private key. Otherwise, signature verification would not be successful.
Data must be same. Every bit should be same.
Hash algorithm used in signing and verification must be same.
After that, signature generated in signing should be same as signature used in verification.
Any mismatch will result in signature mismatch.
I believe this might help you to find out where it is going wrong.