如何在iOS中使用PKCS8 RSA DER私钥? [英] How can I use a PKCS8 RSA DER Private Key in iOS?

查看:704
本文介绍了如何在iOS中使用PKCS8 RSA DER私钥?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在运行时,我的iOS应用程序接收到带有其他人的Java生成的带有公共-私有RSA密钥对的文件:

At run time, my iOS application receives a file with a public-private RSA key-pair, generated by someone else's Java:

KeyPairGenerator keygenerator;
keygenerator = KeyPairGenerator.getInstance("RSA");
keygenerator.initialize(4096);

KeyPair keypair = keygenerator.generateKeyPair();
PrivateKey privateKey = keypair.getPrivate().getEncoded();
PublicKey publicKey = keypair.getPublic().getEncoded();

我已经使用

I have successfully read and used the public key, using this method, which strips some preamble from the key.

我现在要使用 private 键.相同的方法行不通,我认为前言有些不同.该博客建议它正在导入PKCS#1 PEM密钥,但随后说它们是二进制的,因此我认为它们仅表示Base64编码的DER密钥.我还发现,也许我拥有的密钥是 PKCS#8 编码的代替.

I now want to use the private key. The same method doesn't work, I assumed the preamble is different somehow. The blog suggested that it was importing PKCS#1 PEM keys, but then says they're binary, so I think they just mean Base64-encoded DER keys. I also found that maybe the keys I have are PKCS#8 encoded instead.

当然可以使用

openssl pkcs8 -nocrypt -inform der < pk8.der > pvt.pem

使用示例私钥和openssl不会抱怨.

on a sample private key and openssl doesn't complain.

公钥是PKCS#1,私钥是PKCS#8,这有意义吗?

Would it make sense that the public key was PKCS#1 and the private PKCS#8?

但是我真的很想使用CommonCrypto和安全框架,而不是尽可能地使用 链接到OpenSSL.在Mac OS上, libsecurity 中具有功能来读取PKCS#8,但这尚未到达iOS.老实说,我确实尝试阅读源代码,但是我无法弄清他们实际在哪里剥离密钥.

But I really would like to use CommonCrypto and the Security Framework rather than linking against OpenSSL if I possibly can. On Mac OS there are functions in libsecurity to read PKCS#8, but this hasn't made it to iOS yet. I did, honestly, try reading the source but I can't work out where they actually strip the key.

[TL; DR]如何删除版本和算法 DER私钥中的PKCS#8字段,然后使用CommonCrypto或某些C/C ++/ObjC来获取普通密钥?

[TL;DR] How can I strip the version and algorithm PKCS#8 fields from the DER private key, and just get the plain key, using either CommonCrypto or some C/C++/ObjC?

推荐答案

如果没有OpenSSL,我将无法解决问题.因此,这是确实使用OpenSSL的解决方案.

I couldn't solve the problem without OpenSSL. So here is a solution that does use OpenSSL.

假设您有一个带有密钥的NSData,称为privateKey,另一个是要签名的signableData.

Assuming you have a NSData called privateKey with the key, and another called signableData which you want to sign.

#import <openssl/x509.h>
#import <openssl/pem.h>

NSURL *cacheDir = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
NSString *infile = [[cacheDir URLByAppendingPathComponent:@"privkey.der"] path];

NSError *error;
[privateKey writeToFile:infile options:NSDataWritingFileProtectionComplete error:&error];
if (error) {
    NSLog(@"%@", error);
} else {
    BIO *in = BIO_new_file([infile cStringUsingEncoding:NSUTF8StringEncoding], "rb");
    PKCS8_PRIV_KEY_INFO *p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
    NSLog(@"%i", p8inf->broken);
    EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
    PKCS8_PRIV_KEY_INFO_free(p8inf);
    BIO_free(in);

    uint8_t * cipherBuffer = NULL;

    // Calculate the buffer sizes.
    unsigned int cipherBufferSize = RSA_size(pkey->pkey.rsa);
    unsigned int signatureLength;

    // Allocate some buffer space. I don't trust calloc.
    cipherBuffer = malloc(cipherBufferSize);
    memset((void *)cipherBuffer, 0x0, cipherBufferSize);

    unsigned char *openSSLHash = SHA1(signableData.bytes, signableData.length, NULL);
    int success = RSA_sign(NID_sha1, openSSLHash, 20, cipherBuffer, &signatureLength, pkey->pkey.rsa);
    if (success) NSLog(@"WIN");


    NSData *signed = [NSData dataWithBytes:(const void*)cipherBuffer length:signatureLength];    

    EVP_PKEY_free(pkey);
}

这篇关于如何在iOS中使用PKCS8 RSA DER私钥?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆