2015-06-24 12 views
5

Tôi đang sử dụng Apple Security Framework. Tôi có thể đăng nhập và sau đó xác minh thành công tất cả trên OS X, nhưng khi tôi cố gắng sử dụng SecKeyRawVerify trên iOS nó không thành công với -9809 lỗi.Đăng nhập vào OS X, Xác minh trên iOS và OSStatus -9809

Tôi đã chơi với nhiều tùy chọn đệm PKCS khác nhau và nhiều thuộc tính khác nhưng tôi không thể thực hiện việc này để xác minh chính xác.

Lưu ý rằng mã bên dưới có thể bị rò rỉ khắp nơi, chỉ cần cố gắng làm cho nó hoạt động đúng cách trước.

OS đang X Ký:

NSData* signData(NSData* plainData, SecKeyRef privateKey) { 
    CFErrorRef error; 

    /* Create the transform objects */ 
    SecTransformRef signer = SecSignTransformCreate(privateKey, &error); 
    if (error) { CFShow(error); exit(-1); }          

    /* Explicitly set padding type (necessary?) */ 
    SecTransformSetAttribute(signer, 
          kSecPaddingKey, 
          kSecPaddingPKCS1Key, 
          &error); 
    if (error) { CFShow(error); exit(-1); } 

    /* Specify digest type */ 
    SecTransformSetAttribute(signer, 
          kSecDigestTypeAttribute, 
          kSecDigestSHA1, 
          &error); 
    if (error) { CFShow(error); exit(-1); } 

    /* OS X calculates SHA1 hash/signature for us */ 
    SecTransformSetAttribute(signer, 
          kSecTransformInputAttributeName, 
          plainData, 
          &error); 
    if (error) { CFShow(error); exit(-1); } 

    CFTypeRef signature = SecTransformExecute(signer, &error); 
    if (error || !signature) { CFShow(error); exit(-1); } 

    CFRelease(signer); 

    return signature; 
} 

và mã xác minh iOS:

+ (NSData *)verifyData:(NSData *)data 
       usingKey:(SecKeyRef)publicKey { 
    size_t signatureByteLength = SecKeyGetBlockSize(publicKey); 

    if (signatureByteLength > data.length) 
    { 
     NSLog(@"Signature length is greater that data length."); 
     return nil; 
    } 

    NSData *signature = [data subdataWithRange:NSMakeRange(0, signatureByteLength)]; 
    NSData *plainData = [data subdataWithRange:NSMakeRange(signatureByteLength, data.length - signatureByteLength)]; 

    NSLog(@"signatureLength='%lu', signatureBytes='%@', plainDataLength=%lu", (unsigned long)signature.length, signature, (unsigned long)plainData.length); 

    size_t hashByteLength = CC_SHA1_DIGEST_LENGTH; 
    uint8_t* hashBytes = (uint8_t *)malloc(hashByteLength); 

    if (CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) 
    { 
     NSData *b = [NSData dataWithBytes:hashBytes length:hashByteLength]; 
     NSLog(@"hashBytesLength='%lu', hashBytes=%@", (unsigned long)b.length, b); 

     OSStatus status = SecKeyRawVerify(publicKey, 
            kSecPaddingPKCS1SHA1, // I have also tried kSecPaddingPKCS1, doesn't work 
            hashBytes, 
            hashByteLength, 
            (uint8_t *)[signature bytes], 
            signatureByteLength); 

     switch (status) 
     { 
      case errSecSuccess: 
       NSLog(@"SecKeyRawVerify success."); 
       return plainData; 

      case errSSLCrypto: 
       NSLog(@"SecKeyRawVerify failed: underlying cryptographic error"); 
       break; 

      case errSecParam: 
       NSLog(@"SecKeyRawVerify failed: one or more parameters passed to a function where not valid."); 
       break; 

      default: 
       NSLog(@"SecKeyRawVerify failed: error code '%d'", (int)status); 
       break; 
     } 
    } 
    return nil; 
} 

Tôi tạo ra các phím tư nhân và công cộng thông qua dòng lệnh sử dụng lệnh OpenSSL sau:

1. // Generate private and public key pair 
openssl genrsa -out rsaPrivate.pem 1024 

1a. // Generate public key 
openssl rsa -in rsaPrivate.pem -pubout -outform PEM -out rsaPublic.pem 

2. //Create a certificate signing request with the private key 
openssl req -new -key rsaPrivate.pem -out rsaCertReq.csr 

3. //Create a self-signed certificate with the private key and signing request 
openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey rsaPrivate.pem -out rsaCert.crt 

4. //Convert the certificate to DER format: the certificate contains the public key 
openssl x509 -outform der -in rsaCert.crt -out rsaCert.der 

Bất kỳ trợ giúp nào được đánh giá cao.

+0

Có liên quan (có thể trùng lặp): [SecKeyRawVerify - OSError Unknown (-9809)] (http://stackoverflow.com/q/10757033). – jww

+0

@jww Tôi đã xem bài đăng đó và đã thử giải pháp của họ nhưng không giải quyết được sự cố, thật không may. – Maurizio

Trả lời

3

Tôi đã tìm ra vấn đề. Mã tôi đăng là chính xác, nhưng đệm cần phải được thiết lập như là kSecPaddingPKCS1SHA1 mỗi file SecKey.h tiêu đề:

If you are verifying a proper PKCS1-style signature, with DER encoding 
of the digest type - and the signedData is a SHA1 digest - use 
kSecPaddingPKCS1SHA1. 

Ngoài ra, bạn có thể muốn chắc chắn rằng khóa công khai của bạn ở định dạng .der là đúng một :)

+0

Ồ, làm tốt lắm. Tôi nghĩ rằng 'SecKeyRawVerify' đã * không * xử lý bất kỳ chi tiết mã hóa/padding nào. Tôi nghĩ nó chỉ thực hiện lũy thừa. – jww

0
if (CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) 
{ 
    NSData *b = [NSData dataWithBytes:hashBytes length:hashByteLength]; 
    NSLog(@"hashBytesLength='%lu', hashBytes=%@", (unsigned long)b.length, b); 
    ... 
} 

Dường như bạn không mã hóa và áp dụng đệm chính xác. Mã hóa và đệm được áp dụng trước khi băm. Xem RFC 3447, Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1 (hoặc đặc tả PKCS # 1).

+0

Một chút nhầm lẫn bởi câu trả lời của bạn ... Phương thức 'CC_SHA1' tính toán băm, nhưng nó không thực sự được sử dụng cho đến khi tôi gọi' SecKeyRawVerify' nơi tất cả các tham số được truyền vào và việc xác minh được xử lý nội bộ. 'SecKeyRawVerify' lấy giá trị băm (digest) như một tham số, cùng với phần còn lại (phím pub, chữ ký, vv). Vì các tham số cho bộ chọn đó có trong phần đệm và băm tôi tin rằng nó nên xử lý tất cả những gì trong một bước. – Maurizio

Các vấn đề liên quan