0

私はRSAアルゴリズムを実装しようとしていますが、アップルのリファレンスに従いました。しかし、uint8_tをNSData、NSStringに変換する際に問題が発生します。

私はこれまでにこれを行いました。これらの関数は参照で定義されています

-(void)test{
    [self generateKeyPairPlease];
    NSData *data = [self encryptWithPublicKey]; //All goes well until here
    [self decryptWithPrivateKey:data]; 

}

暗号化のために私はしました。

- (NSData *)encryptWithPublicKey
{
    OSStatus status = noErr;

    size_t cipherBufferSize;
    uint8_t *cipherBuffer;                     // 1

// [cipherBufferSize]
    const uint8_t dataToEncrypt[] = "the quick brown fox jumps "
                            "over the lazy dog\0"; // 2
    size_t dataLength = sizeof(dataToEncrypt)/sizeof(dataToEncrypt[0]);

    SecKeyRef publicKey = NULL;                                 // 3

    NSData * publicTag = [NSData dataWithBytes:publicKeyIdentifier
             length:strlen((const char *)publicKeyIdentifier)]; // 4

    NSMutableDictionary *queryPublicKey =
                            [[NSMutableDictionary alloc] init]; // 5

    [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
    [queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
    [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
                                                                // 6

    status = SecItemCopyMatching
    ((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKey); // 7

//  Allocate a buffer

    cipherBufferSize = SecKeyGetBlockSize(publicKey);
    cipherBuffer = malloc(cipherBufferSize);

//  Error handling

    if (cipherBufferSize < sizeof(dataToEncrypt)) {
        // Ordinarily, you would split the data up into blocks
        // equal to cipherBufferSize, with the last block being
        // shorter. For simplicity, this example assumes that
        // the data is short enough to fit.
        printf("Could not decrypt.  Packet too large.\n");
        return NULL;
    }

    // Encrypt using the public.
    status = SecKeyEncrypt(    publicKey,
                                kSecPaddingPKCS1,
                                dataToEncrypt,
                                (size_t) dataLength,
                                cipherBuffer,
                                &cipherBufferSize
                                );                              // 8

//  Error handling
//  Store or transmit the encrypted text

    if (publicKey) CFRelease(publicKey);

    NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:dataLength];

    free(cipherBuffer);

    return encryptedData;
}

しかし、(復号化された結果)をdecryptWithPrivateKeyに変換できません 。最初に、印刷時にバイトを正しく表示して変換しようとしましたが、文字列に変換されていません。uint8_t *plainBufferNSStringNSDataNSLogNSData

- (void)decryptWithPrivateKey: (NSData *)dataToDecrypt
{
    OSStatus status = noErr;

    size_t cipherBufferSize = [dataToDecrypt length];
    uint8_t *cipherBuffer = (uint8_t *)[dataToDecrypt bytes];

    size_t plainBufferSize;
    uint8_t *plainBuffer;

    SecKeyRef privateKey = NULL;

    NSData * privateTag = [NSData dataWithBytes:privateKeyIdentifier
                                         length:strlen((const char *)privateKeyIdentifier)];

    NSMutableDictionary *queryPrivateKey = [[NSMutableDictionary alloc] init];

    // Set the private key query dictionary.
    [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
    [queryPrivateKey setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag];
    [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    // 1

    status = SecItemCopyMatching
    ((__bridge CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKey); // 2

    //  Allocate the buffer
    plainBufferSize = SecKeyGetBlockSize(privateKey);
    plainBuffer = malloc(plainBufferSize);

    if (plainBufferSize < cipherBufferSize) {
        // Ordinarily, you would split the data up into blocks
        // equal to plainBufferSize, with the last block being
        // shorter. For simplicity, this example assumes that
        // the data is short enough to fit.
        printf("Could not decrypt.  Packet too large.\n");
        return;
    }

    //  Error handling

    status = SecKeyDecrypt(    privateKey,
                           kSecPaddingPKCS1,
                           cipherBuffer,
                           cipherBufferSize,
                           plainBuffer,
                           &plainBufferSize
                           );                              // 3

    //*******************************************************************************
    // Not able to convert  uint8_t *plainBuffer to string 
    // I also tried to convert it into NSData and then try to convert it into NSString but can't 
    //What Should i do here to get string back


  if(privateKey) CFRelease(privateKey);
}
@end

uint8_t plainBuffer復号化された結果をNSDataに、NSStringまたは単にNSString文字列を取り戻すために変換する方法を知りたいです。暗号化とキー生成コードについては、このリファレンスを参照してください。

前もって感謝します..

4

3 に答える 3

6

私はこの質問が古く、解決済みとしてマークされていることを知っていますが、同様の問題でここに到着しました。私が見つけたのは、Appledocsの行にある暗号化方法にエラーがあるようだということです

NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:dataLength];

ここでは、datalengthが間違った変数です。私はそれをcipherbuffersizeに置き換えました

NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];

そして今、すべてがうまく機能しています。それが私以外の誰かに役立つことを願っています。

于 2013-03-19T14:29:19.327 に答える
1

最も可能性の高い問題は、+[stringWithCharacters:length:]Unicode文字(より正確にはUTF-16コードポイント)を期待する呼び出していることですが、おそらくUTF-8または別の8ビットエンコーディングを使用しています。

使用しているエンコーディングを知っている必要があるので、呼び出すことができます+[stringWithCString:encoding:](または、UTF-8の場合+[stringWithUTF8String:]は略して)。

とは異なりstringWithCharacters、これらのメソッドは長さがかからず、データがnullで終了することを想定していることに注意してください。したがって、データに常にターミネータが含まれることが確実でない限り、データを明示的にチェックするか、文字列を割り当ててからを呼び出す必要があります-[initWithBytes:length:encoding:]

平文が暗号化される前にどの文字セットであったかわからない場合は、調べる必要があります。人間として、特にそれがほとんどASCIIである場合は、それを見ることでよくわかります。NSDataバッファを使用してを作成し、それをログに記録して、16進数を確認します。UTF-16の場合、ASCII文字はnullと交互になり、。'Hello'になります48 00 65 00 6C 00 6C 00 6F 00。しかし、コンピューターは推測をうまく行うことはできません。(+[stringWithContentsOfFile:usedEncoding:error:]通常、正しく理解される理由はcom.apple.TextEncoding、ほとんどのCocoaアプリがファイルを保存するときに書き込む拡張属性を調べるためです。)

于 2013-01-14T19:04:28.680 に答える
0

私はこのコードに従うことで問題を解決することができ ます。それは同じコードですが、文字列のエンコーディングが異なります。encryptWithPublicKey私が使用した関数では

uint8_t *dataToEncrypt= (uint8_t *)[@"the quick brown fox jumps over the lazy dog" UTF8String];

それ以外の

const uint8_t dataToEncrypt[] = "the quick brown fox jumps " "over the lazy dog\0";

そしてdecryptWithPrivateKey私はこれを使ってデコードしました

 NSData *decryptedData = [NSData dataWithBytes:plainBuffer length:plainBufferSize];
 NSString *decryptedString = [[[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding] autorelease];
于 2013-01-16T19:37:36.580 に答える