PHP'nin openssl_sign SSCrypto belirtisi farklı imza üretir

4 Cevap php

PHP ile yazılmış bir yazılım için bir OS X istemcisi yazıyorum. Bu yazılım komutları almak ve çalıştırmak için basit bir RPC arayüzü kullanır. RPC istemci o hiçbir MITM bunlardan herhangi birini değiştirebilirsiniz emin gönderdiği komutları imzalamak zorundadır.

Sunucu benim OS X istemcisi gönderilen imzaları kabul değildi Ancak, ben soruşturma başladı ve PHP'nin openssl_sign işlevi Objective-C {[(0) daha belirli bir özel anahtar / veri kombinasyonu için farklı bir imza oluşturur öğrendim }] çerçevesi (openssl lib için sadece bir sarıcı olan):

SSCrypto *crypto = [[SSCrypto alloc] initWithPrivateKey:self.localPrivKey];
NSData *shaed = [self sha1:@"hello"];
[crypto setClearTextWithData:shaed];
NSData *data = [crypto sign];

CtbkSxvqNZ+mAN gibi bir imza üretir ...

PHP kodu

openssl_sign("hello", $signature, $privateKey);

generates a signature like 6u0d2qjFiMbZ+... (For my certain key, of course. base64 encoded)

Bu neden oluyor oldukça shure değilim ve ben başarısız farklı hash algoritmaları ile denedi. PHP belgelerine belirttiği gibi SHA1 varsayılan olarak kullanılır.

Peki neden bu iki işlevi farklı imzalar oluşturmak ve nasıl benim Objective-C kısmı openssl_verify kabul edecek Phps bir imza oluşturmak için alabilirim?

Not: Ben tuşları ve verilerin doğru olduğunu kontrol çift!

4 Cevap

Tamam, epeyce saat sürdü. Buradaki budur:

Eğer openssl_sign işlevini çağırdığınızda, PHP dahili openssl lib tarafından sağlanan EVP API kullanır. EVP RSA_private_encrypt gibi temel işlevler için "yüksek seviyeli" bir API. Aradığınızda Yani base64_encode(openssl_sign('hello', $signature, $privKey)) bu openssl ikili kullanarak komut satırında böyle bir şey yapmak için benzer:

echo -n "hello"| openssl dgst -sha1 -sign priv.key | openssl enc -base64

ve NOT

echo -n "hello" | openssl dgst -sha1 | openssl rsautl -encrypt priv.key | openssl enc -base64

I don't know why this produces different output , but it does. If someone has an idea why they differ: please share!
However, as I'm using the SSCrypto framework I rewrote the -sign (and -verify) function with EVP calls (abstract):

OpenSSL_add_all_digests();
EVP_MD_CTX_init(&md_ctx);
EVP_SignInit(&md_ctx, mdtype);
EVP_SignUpdate(&md_ctx, input, inlen);
if (EVP_SignFinal(&md_ctx, (unsigned char*) outbuf, (unsigned int *)&outlen, pkey)) {
    NSLog(@"signed successfully.");
}

Ve işte: PHP aldığım gibi ben aynı imzaları olsun. Oh ve kayıt için: PHP pkcs dolgu kullanır.

Eğer bana doğru yönde işaret için teşekkür ederim çocuklar!

Sizin kod parçacığını Ben aynı sorun vardı, büyük bir yardım olduğunu ve aynı sorunu olan herkese yardımcı olur, ben, senin hattına dayalı aşağıdaki yöntemi ile geldi.

- (NSData *)getSignature {
NSString * signString = [self getSignatureText];
NSData * privateKeyData = [self getPrivateKey];

BIO *publicBIO = NULL;
EVP_PKEY *privateKey = NULL;

if (!(publicBIO = BIO_new_mem_buf((unsigned char *)[privateKeyData bytes], [privateKeyData length]))) {
    NSLog(@"BIO_new_mem_buf() failed!");
    return nil;
}

if (!PEM_read_bio_PrivateKey(publicBIO, &privateKey, NULL, NULL)) {
    NSLog(@"PEM_read_bio_PrivateKey() failed!");
    return nil;
}   

const char * data = [signString cStringUsingEncoding:NSUTF8StringEncoding];
unsigned int length = [signString length];
int outlen;
unsigned char * outbuf[EVP_MAX_MD_SIZE];
const EVP_MD * digest = EVP_md5();
EVP_MD_CTX md_ctx;

EVP_MD_CTX_init(&md_ctx);
EVP_SignInit(&md_ctx, digest);
EVP_SignUpdate(&md_ctx, data, length);
if (EVP_SignFinal(&md_ctx, (unsigned char*) outbuf, (unsigned int *) &outlen, privateKey)) {
    NSLog(@"Signed successfully.");
}
EVP_MD_CTX_cleanup(&md_ctx);
EVP_PKEY_free(privateKey);

NSData * signature = [NSData dataWithBytes:outbuf length:outlen];

return signature;

}

Bu Objective-C imzalanması ise PHP, "hello" imzalanması gibi görünüyor bana sha1("hello"). Yani, ben dokümanlar okumak yoludur, PHP'nin uygulayarak aksine openssl_sign verilere sha1, imzalama iç mekaniği varsayılan sha1 kullanıyor imzalamadan önce.

O giderir, ama rsautl kullanımınız yanlış gibi görünüyor değil. Muhtemelen rsautl-işareti yerine rsautl-şifrelemek kullanarak olmalıdır