X.509 RSA Encryption/Decryption iOS

后端 未结 1 1382
陌清茗
陌清茗 2021-02-06 10:55

I need to implement encryption / decryption using a X.509 RSA public/private key pair.

So far, I have something which I think will work for encryption, but I have no way

1条回答
  •  北海茫月
    2021-02-06 11:09

    Where you are stuck

    It seems your private key is encrypted (openssl asked you for a password on the command line), yet you do not decrypt it when you try to open it. Besides, private_key.pem is an RSA key, not a certificate, so you should use PEM_read_RSAPrivateKey.

    The following decoding code should work:

    int pass_cb(char *buf, int size, int rwflag, void* password) {
        snprintf(buf, size, "%s", (char*) password);
        return strlen(buf);
    }
    
    +(void)readTest{
        FILE *fp;
        RSA *x;
        NSString *path =[[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"pem"];
        fp=fopen([path UTF8String],"r");
    
        x = PEM_read_RSAPrivateKey(fp,&x,pass_cb,"key password");
    
        if (x == NULL) {
            NSLog(@"Cant Read File"); // This ALWAYS fires
        }
    
        fclose(fp);
        X509_free(x);
    }
    

    Alternatively, you could generate a non-encrypted key. Pass -nodes to openssl when creating the keys and the certificate.

    Please note that you might need to make sure OpenSSL is properly initialized with:

    SSL_library_init();
    OpenSSL_add_all_algorithms();
    

    Besides, OpenSSL generates error messages that could help you through development. You load the error strings with:

    SSL_load_error_strings();
    

    And you could call:

    ERR_print_errors_fp(stderr);
    

    RSA encryption and decryption on iOS

    OpenSSL is not the only solution as Security framework on iOS contains everything you need. I guess you turned to OpenSSL because you did not know how to convert your private key file to valid parameters for SecKeyDecrypt.

    The trick is to produce a PKCS#12 file and to call SecPKCS12Import.

    You can produce this file with OpenSSL:

    openssl x509 -inform der -outform pem -in public_key.der -out public_key.pem
    openssl pkcs12 -export -in public_key.pem -inkey private_key.pem -out private_key.p12
    

    This will ask you for an export password. This password should be passed to SecPKCS12Import ("key password" below).

    NSString *privateKeyPath = [[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"p12"];
    NSData *pkcs12key = [NSData dataWithContentsOfFile:privateKeyPath];
    NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys: @"key password", kSecImportExportPassphrase, nil];
    CFArrayRef              importedItems = NULL;
    OSStatus returnCode = SecPKCS12Import(
                          (__bridge CFDataRef) pkcs12key,
                          (__bridge CFDictionaryRef) options,
                          &importedItems
                          );
    

    importedItems is an array containing all imported PKCS12 items, and basically, the "identity" (private key + certificate).

    NSDictionary* item = (NSDictionary*) CFArrayGetValueAtIndex(importedItems, 0);
    SecIdentityRef  identity = (__bridge SecIdentityRef) [item objectForKey:(__bridge NSString *) kSecImportItemIdentity];
    SecKeyRef privateKeyRef;
    SecIdentityCopyPrivateKey(identity, &privateKeyRef);
    

    Then you can use privateKeyRef to perform the decryption with SecKeyDecrypt. To match your encryption routine:

    size_t cipherLen = [content length];
    void *cipher = malloc(cipherLen);
    [content getBytes:cipher length:cipherLen];
    size_t plainLen = SecKeyGetBlockSize(privateKeyRef) - 12;
    void *plain = malloc(plainLen);
    
    OSStatus decryptReturnCode = SecKeyDecrypt(privateKeyRef, kSecPaddingPKCS1, cipher, cipherLen, plain, &plainLen);
    

    0 讨论(0)
提交回复
热议问题