简体   繁体   English

如何在iOS中使用PKCS8 RSA DER私钥?

[英]How can I use a PKCS8 RSA DER Private Key in iOS?

At run time, my iOS application receives a file with a public-private RSA key-pair, generated by someone else's Java: 在运行时,我的iOS应用程序接收一个文件,该文件具有由其他人的Java生成的公共 - 私有RSA密钥对:

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. 我已经成功地读取和使用公共密钥,使用这种方法 ,这条从一些关键序言。

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. 该博客建议它导入PKCS#1 PEM密钥,但后来说它们是二进制的,所以我认为它们只是意味着Base64编码的DER密钥。 I also found that maybe the keys I have are PKCS#8 encoded instead. 我还发现,也许我拥有的密钥是PKCS#8编码。

Certainly I can use 当然我可以使用

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

on a sample private key and openssl doesn't complain. 在一个示例私钥和openssl不抱怨。

Would it make sense that the public key was PKCS#1 and the private PKCS#8? 公钥是PKCS#1还是私有PKCS#8会有意义吗?

But I really would like to use CommonCrypto and the Security Framework rather than linking against OpenSSL if I possibly can. 但我真的想使用CommonCrypto和安全框架,而不是在可能的情况下链接OpenSSL。 On Mac OS there are functions in libsecurity to read PKCS#8, but this hasn't made it to iOS yet. 在Mac OS上, libsecurity中有函数来读取PKCS#8,但这还没有进入iOS。 I did, honestly, try reading the source but I can't work out where they actually strip the key. 老实说,我确实尝试过读源,但我无法解决他们实际剥离密钥的问题。

[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? [TL; DR]如何从DER私钥中删除版本和算法 PKCS#8字段,并使用CommonCrypto或某些C / C ++ / ObjC获取普通密钥?

I couldn't solve the problem without OpenSSL. 没有OpenSSL,我无法解决问题。 So here is a solution that does use OpenSSL. 所以在这里是使用OpenSSL的解决方案。

Assuming you have a NSData called privateKey with the key, and another called signableData which you want to sign. 假设您有一个名为privateKey的NSData和密钥,另一个名为signableData,您要签名。

#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);
}

You can see how a der key looks in ASN1 structure in this webpage: https://lapo.it/asn1js/ 您可以在此网页中查看按键在ASN1结构中的外观: https//lapo.it/asn1js/

Here is a code from the SwCrypt library, which strips the PKCS8 header from a private key. 这是来自SwCrypt库的代码,它从私钥中剥离PKCS8头。 This is Swift, but you can rewrite it any other language easily. 这是Swift,但您可以轻松地将其重写为任何其他语言。

    static private func stripHeaderIfAny(keyData: NSData) throws -> NSData {
        var bytes = keyData.arrayOfBytes()

        var offset = 0
        guard bytes[offset] == 0x30 else {
            throw SwError.ASN1Parse
        }
        offset += 1

        if bytes[offset] > 0x80 {
            offset += Int(bytes[offset]) - 0x80
        }
        offset += 1

        guard bytes[offset] == 0x02 else {
            throw SwError.ASN1Parse
        }
        offset += 3

        //without PKCS8 header
        if bytes[offset] == 0x02 {
            return keyData
        }

        let OID: [UInt8] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
                            0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00]
        let slice: [UInt8] = Array(bytes[offset..<(offset + OID.count)])

        guard slice == OID else {
            throw SwError.ASN1Parse
        }

        offset += OID.count
        guard bytes[offset] == 0x04 else {
            throw SwError.ASN1Parse
        }

        offset += 1
        if bytes[offset] > 0x80 {
            offset += Int(bytes[offset]) - 0x80
        }
        offset += 1

        guard bytes[offset] == 0x30 else {
            throw SwError.ASN1Parse
        }

        return keyData.subdataWithRange(NSRange(location: offset, length: keyData.length - offset))
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Swift或Objective C中使用PKCS8 RSA DER私钥 - How can I use a PKCS8 RSA DER Private Key in Swift or Objective C 如何在iOS中将十六进制格式rsa私钥转换为PKCS8格式 - how to convert hex format rsa private key to PKCS8 format in iOS 如何从字符串获取PKCS8 RSA私钥/如何从XML获取RSA密钥对 - How to obtain PKCS8 RSA Private Key from string / obtain RSA key pair from XML 使用DER格式的RSA公钥文件进行iOS加密 - iOS Encryption using RSA public key file in DER format 在iOS中创建RSA私钥 - Creating an RSA private key in iOS iOS 中是否需要 RSA 公钥/私钥 SecRefKey? - RSA Public/Private Key SecRefKey Necessary in iOS? iOS:可以在应用程序文档目录中存储RSA私钥(用于解密文本)吗? - iOS: Is it ok to store a RSA private key (use to decrypt text) in your application document directory? iOS:我需要将用户的私钥(RSA)转移到我的应用程序。 文件共享是一个好的解决方案吗? - iOS: I need to transfer user's private key (RSA) to my App. Is file sharing a good solution? RSA私钥-iOS - RSA Private Keys - iOS iOS:如何以编程方式在应用程序中从私钥和x509certificate创建PKCS12(P12)密钥库? - iOS: How to create PKCS12 (P12) keystore from private key and x509certificate in application programmatically?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM