2015-10-16 15 views
11

私の静的ライブラリにはライセンスファイルがあります。私は自分自身で生成されていることを確認したい(変更されていない)。だから、私が読んだことからRSA Signatureを使用するというアイデアがありました。RSA署名の確認iOS

私はインターネット上で見てきたし、これは私が思い付いたものです:

まず:私はhere見つかった情報を秘密鍵と自己署名証明書を生成します。その後

// Generate private key 
openssl genrsa -out private_key.pem 2048 -sha256 

// Generate certificate request 
openssl req -new -key private_key.pem -out certificate_request.pem -sha256 

// Generate public certificate 
openssl x509 -req -days 2000 -in certificate_request.pem -signkey private_key.pem -out certificate.pem -sha256 

// Convert it to cer format so iOS kan work with it 
openssl x509 -outform der -in certificate.pem -out certificate.cer -sha256 

、私は(内容として、日付とアプリ識別子を持つ)ライセンスファイルを作成し、その情報をもとのようにそのファイルの署名を生成hereが見つかりました:

I
// Store the sha256 of the licence in a file 
openssl dgst -sha256 licence.txt > hash 

// And generate a signature file for that hash with the private key generated earlier 
openssl rsautl -sign -inkey private_key.pem -keyform PEM -in hash > signature.sig 

すべての作品がうまくいくと思います。私はどんなエラーも得ず、鍵と証明書と他のファイルを期待通りに入手します。

次へ私のアプリケーションにcertificate.cersignature.sigおよびlicense.txtをコピーします。

署名が私によって署名され、license.txtに有効であるかどうかを確認したいと思います。私は、任意の良い例を見つけることはかなり難しい見つかりましたが、これは私が現在持っているものです。

私が見つけたSeucyrity.Frameworkが署名を検証するためにRSA鍵/証明書とSecKeyRawVerifyを参照するためにSecKeyRefを使用しています。

ファイルから公開鍵を読み込む次の方法があります。

- (SecKeyRef)publicKeyFromFile:(NSString *) path 
{ 
    NSData *myCertData = [[NSFileManager defaultManager] contentsAtPath:path]; 
    CFDataRef myCertDataRef = (__bridge CFDataRef) myCertData; 

    SecCertificateRef cert = SecCertificateCreateWithData (kCFAllocatorDefault, myCertDataRef); 
    CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **) &cert, 1, NULL); 
    SecPolicyRef policy = SecPolicyCreateBasicX509(); 
    SecTrustRef trust; 
    SecTrustCreateWithCertificates(certs, policy, &trust); 
    SecTrustResultType trustResult; 
    SecTrustEvaluate(trust, &trustResult); 
    SecKeyRef pub_key_leaf = SecTrustCopyPublicKey(trust); 

    if (trustResult == kSecTrustResultRecoverableTrustFailure) 
    { 
     NSLog(@"I think this is the problem"); 
    } 
    return pub_key_leaf; 
} 

this SO postに基づいています。私は次の関数

私のプロジェクトでは here

から取られ

BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey) 
{ 
    size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey); 
    const void* signedHashBytes = [signature bytes]; 

    size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH; 
    uint8_t* hashBytes = malloc(hashBytesSize); 
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) { 
     return nil; 
    } 

    OSStatus status = SecKeyRawVerify(publicKey, 
             kSecPaddingPKCS1SHA256, 
             hashBytes, 
             hashBytesSize, 
             signedHashBytes, 
             signedHashBytesSize); 

    return status == errSecSuccess; 
} 

を発見した署名検証のために

私はそうのようなコードを呼び出す:

// Get the licence data 
NSString *licencePath = [[NSBundle mainBundle] pathForResource:@"licence" ofType:@"txt"]; 
NSData *data = [[NSFileManager defaultManager] contentsAtPath:licencePath]; 

// Get the signature data 
NSString *signaturePath = [[NSBundle mainBundle] pathForResource:@"signature" ofType:@"sig"]; 
NSData *signature = [[NSFileManager defaultManager] contentsAtPath:signaturePath]; 

// Get the public key 
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"]; 
SecKeyRef publicKey = [self publicKeyFromFile:publicKeyPath]; 

// Check if the signature is valid with this public key for this data 
BOOL result = PKCSVerifyBytesSHA256withRSA(data, signature, publicKey); 

if (result) 
{ 
    NSLog(@"Alright All good!"); 
} 
else 
{ 
    NSLog(@"Something went wrong!"); 
} 

現在、それは常に言います: "何かが間違ってしまった!"私は何がわかりませんが。私は、公開鍵を取得するメソッドの信頼結果が、kSecTrustResultRecoverableTrustFailureと思っています。これは問題だと思います。 Apple documentationでは、期限切れの証明書の結果である可能性があります。それはここではそうではないようですが。しかし、証明書を生成する方法に何か問題がありますか?

私の質問は、私は間違っていますか、どうすれば修正できるのでしょうか?私はこれについてのドキュメントが非常に疎で読みにくいことがわかります。

私はuploadedがあり、生成された証明書とここで参照されているコードを持つiOSプロジェクトがあります。多分それは便利になるかもしれない。

+1

をあなたは、3-リストを見ればあなたが指摘しているドキュメントには、 "AllStatusBits'"のリストがあります。あなたは、そのエラーに遭遇したときにステータスビットが何であるか把握できますか? –

+0

こんにちは、そのコードを組み込もうとすると、最初のエラーの1つは、 'AllStatusBits'の' CSSM_TP_APPLE_CERT_STATUS'タイプが不明で、そのタイプを取得するためにインクルードするための実際のヘッダーファイルが見つからないようです。インターネット上では、それは '#import 'であるかもしれないが、iOSでは存在しない(それ以上は?) - コードと証明書を使って(http://up.indev.nl/RTR4y0Ou0L.zip)自分のプロジェクトを[アップロードしました。多分役立つかもしれません。 – Matthijn

+0

はい、私はもう一度チェックしましたが、私は[既に](http://up.indev.nl/C5OHOFziPO.png)にセキュリティフレームワークを追加しました。おそらく、iOS版のどこか別の場所に移動したのでしょうか? – Matthijn

答えて

8

問題は、署名ファイルの作成方法にあります。同じ手順を経て、私はバイナリの同等ファイルsignature.sigを生成することができました。だから、signature.sigはあなたのサンプルを使用して、その上ではなくlicense.txt

に基づいています

$ cat hash 
SHA256(licence.txt)= 652b23d424dd7106b66f14c49bac5013c74724c055bc2711521a1ddf23441724 

:私たちは、OpenSSLは、いくつかの接頭辞(や進エンコードハッシュ)を追加見ることができますhashファイル内で見ることによって

そして、で署名ファイルを作成:

openssl dgst -sha256 -sign certificates/private_key.pem licence.txt > signature.sig 

ハッシュ&署名STE pが正しい取得し、サンプルの出力:Alright All good!


私のファイルの最終状態、念のため

- (SecKeyRef)publicKeyFromFile:(NSString *) path 
{ 
    NSData * certificateData = [[NSFileManager defaultManager] contentsAtPath:path]; 
    SecCertificateRef certificateFromFile = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData); 
    SecPolicyRef secPolicy = SecPolicyCreateBasicX509(); 
    SecTrustRef trust; 
    SecTrustCreateWithCertificates(certificateFromFile, secPolicy, &trust); 
    SecTrustResultType resultType; 
    SecTrustEvaluate(trust, &resultType); 
    SecKeyRef publicKey = SecTrustCopyPublicKey(trust); 
    return publicKey; 
} 

BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey) 
{ 
    uint8_t digest[CC_SHA256_DIGEST_LENGTH]; 
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], digest)) 
     return NO; 

    OSStatus status = SecKeyRawVerify(publicKey, 
             kSecPaddingPKCS1SHA256, 
             digest, 
             CC_SHA256_DIGEST_LENGTH, 
             [signature bytes], 
             [signature length]); 

    return status == errSecSuccess; 
} 

PS:malloc


編集リークでした。

現在のsignature.sigファイルを-iとして機能させるにはsの、あなたはopensslの(追加の接頭辞、六角ハッシュ、および改行\n)と同様の工程を生成する必要があり、その後、kSecPaddingPKCS1SecKeyRawVerifyにこのデータを渡していないkSecPaddingPKCS1SHA256

BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey) 
{ 
    uint8_t digest[CC_SHA256_DIGEST_LENGTH]; 
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], digest)) 
     return NO; 

    NSMutableString *hashFile = [NSMutableString stringWithFormat:@"SHA256(licence.txt)= "]; 
    for (NSUInteger index = 0; index < sizeof(digest); ++index) 
     [hashFile appendFormat:@"%02x", digest[index]]; 

    [hashFile appendString:@"\n"]; 
    NSData *hashFileData = [hashFile dataUsingEncoding:NSNonLossyASCIIStringEncoding]; 

    OSStatus status = SecKeyRawVerify(publicKey, 
             kSecPaddingPKCS1, 
             [hashFileData bytes], 
             [hashFileData length], 
             [signature bytes], 
             [signature length]); 

    return status == errSecSuccess; 
} 
+0

「SecTrustEvaluate」で 'kSecTrustResultRecoverableTrustFailure'を取得しても、署名は正常に検証されています。 – Lefteris

+0

kSecTrustResultRecoverableTrustFailureの問題は、証明書が自己署名されていると思っています。有効である。 (Apple)の信頼できる当局から証明書を取得する必要があります。 (ver * s * gnなど) – blld

+0

またはホストiOSデバイスに証明書をインストールしてください(オプションではないようです) – blld