本文介绍了在iOS库中生成CSR?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以在iOS中生成CSR(证书签名请求),以及是否有库。我想生成一个请求,使用扩展中的私钥对其进行签名,然后将CSR请求发送回服务器。

I want to see if is possible to generate a CSR (Certificate Signing Request) in iOS, and if there is a library for it. I want to generate a request, sign it with a private key from an extension, and then send the CSR request back to the server.

这可能,并且有一个很好的库吗?

Is this possible, and is there a good library for it?

谢谢

推荐答案

是的,这是可能的,但并不简单,因为iOS无法使用标准格式的键,因为你可以想到

Yes, it is possible but is not simple at all because iOS do not work with standard formats for keys as you could think

我已成功使用此库生成PCKS#10格式的CSR,其密钥由KeyChain和以DER格式编码(二进制)。

I have used this library successfully to generate a CSR in PCKS#10 format with a key generated in KeyChain and encoded in DER format (binary).

func createCertificationRequest(keyId: String, C: String?, CN: String?, O:String?, SERIALNAME:String? ) -> String {

        //Replace this with your mechanism to get the private and public key
        let publicKey = loadKeyStringFromKeyChainAsNSData(PUBLIC_KEY + keyId)
        let privateKey = loadKeySecKeyFromKeyChain(PRIVATE_KEY + keyId)

        //SCCSR from ios-csr library
        let sccsr : SCCSR = SCCSR()

        sccsr.commonName = CN;
        sccsr.organizationName = O;
        sccsr.countryName = C;

        //    // aditional data you can set
        //    sccsr.countryName = @"";
        //    sccsr.organizationalUnitName = @"";
        //    sccsr.subjectDER = nil;
        //    //
        //
        let certificateRequest = sccsr.build(publicKey, privateKey: privateKey)
        let certificateRequestB64 = certificateRequest.base64EncodedStringWithOptions(NSDataBase64EncodingOptions())

        let certificateRequestPEM =
            "-----BEGIN CERTIFICATE REQUEST-----\\n" + certificateRequestB64 + "\\n-----END CERTIFICATE REQUEST-----\\n"

        return certificateRequestPEM

    }

在此之后,您可以使用DER(格式)将CSR发送到服务器,或者根据服务的功能以PEM格式(base64)进行编码

After this, you can send the CSR to server in DER (format) or encode in PEM format (base64) depending of the capabilities of your serv

我猜你错过了最后一步,将X509从服务器返回到设备进行存储

I guess you are missed the final step, returning the X509 from server to device to be stored

我还包含帮助使用iOS-KeyChain生成密钥的代码

I include also the code to help generating keys using iOS-KeyChain

let KEY_SIZE = 2048
let PUBLIC_KEY = "mysystem.publickey."
let PRIVATE_KEY = "mysystem.privatekey."

 // Generates a key pair in KeyChain using keyId as identifier and returns the public key
 // publicKey -->PUBLIC_KEY + keyId
 // privateKey --> PRIVATE_KEY + keyId
 // KEY_SIZE is stablished globally
func generateKeyPairInKeyChain(keyId: String) -> String {

    let privateAttributes = [String(kSecAttrIsPermanent): true,
        String(kSecAttrApplicationTag): PRIVATE_KEY + keyId,
        String(kSecAttrIsPermanent): kCFBooleanTrue]
    let publicAttributes = [String(kSecAttrIsPermanent): true,
        String(kSecAttrApplicationTag): PUBLIC_KEY + keyId,
        String(kSecAttrIsPermanent): kCFBooleanTrue]

    let pairAttributes = [String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecAttrKeySizeInBits): KEY_SIZE,
        String(kSecPublicKeyAttrs): publicAttributes,
        String(kSecPrivateKeyAttrs): privateAttributes]

    //Ensure that keychain has no key with keyId identifier
    deleteKeyPairFromKeyChain(keyId)

    var publicRef: SecKeyRef?
    var privateRef: SecKeyRef?

    //Generate the keys and recover the references in publicRef and privateRf
    switch SecKeyGeneratePair(pairAttributes, &publicRef, &privateRef) {
        case noErr:
            // Get the public key as a String
            let publicKeyStr = loadKeyStringFromKeyChain(PUBLIC_KEY + keyId)
            return publicKeyStr
        default:
            return ""
    }
}



公用事业



以下包括用于生成CSR或密钥的实用程序功能。您将看到更改结果类型基本相同(需要一些额外的工作来简化...)

Utilities

The following includes the utility functions used generating CSR or keys. You will see that are basically the same changing the type of result (some extra work is needed to simplify...)

//Delete an existing keypair from keychain (public + private)
func deleteKeyPairFromKeyChain(keyId: String) {
    deleteRSAKeyFromKeychain(PRIVATE_KEY + keyId)
    deleteRSAKeyFromKeychain(PUBLIC_KEY + keyId)
}

// Delete existing RSA key from keychain
private func deleteRSAKeyFromKeychain(tagName: String) {
    let queryFilter: [String: AnyObject] = [
        String(kSecClass)             : kSecClassKey,
        String(kSecAttrKeyType)       : kSecAttrKeyTypeRSA,
        String(kSecAttrApplicationTag): tagName
    ]
    let status: OSStatus = SecItemDelete(queryFilter)
    NSLog("private or public deletion result is: " + status.description)
}

// Finds the SecKeyRef corresponding to the parameter key and returns it as a String
private func loadKeyStringFromKeyChain(key: String) -> String {
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecAttrKeySizeInBits): KEY_SIZE,
        String(kSecClass): kSecClassKey,
        String(kSecAttrApplicationTag): key,
        kSecReturnData as String : kCFBooleanTrue ]

    var dataTypeRef: AnyObject? = nil
    var resultData: NSData? = nil

    let status: OSStatus = withUnsafeMutablePointer(&dataTypeRef) { SecItemCopyMatching(query as NSDictionary, UnsafeMutablePointer($0)) }
    NSLog("SecItemCopyMatching: " + status.description)

    if status == errSecSuccess {
        NSLog("private or public debug description is: " + dataTypeRef.debugDescription)
        resultData = dataTypeRef as? NSData
        let resultStr = resultData?.base64EncodedStringWithOptions([])
        NSLog("private or public String is: " + resultStr!)
        return resultStr!
    } else {
        NSLog("no key found!!!!")
        return ""
    }
}

// Finds the SecKeyRef corresponding to the parameter key and returns it
func loadKeySecKeyFromKeyChain(key: String) -> SecKeyRef {
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecAttrKeySizeInBits): KEY_SIZE,
        String(kSecClass): kSecClassKey,
        String(kSecAttrApplicationTag): key,
        kSecReturnRef as String : kCFBooleanTrue ]

    var dataTypeRef: Unmanaged<AnyObject>? = nil
    var resultData: SecKeyRef? = nil

    let status: OSStatus = withUnsafeMutablePointer(&dataTypeRef) { SecItemCopyMatching(query as NSDictionary, UnsafeMutablePointer($0)) }
    NSLog("SecItemCopyMatching: " + status.description)

    if status == errSecSuccess {
        NSLog("private or public debug description is: " + dataTypeRef.debugDescription)
        resultData = (dataTypeRef!.takeRetainedValue() as! SecKeyRef)
        NSLog("SecItemCopyMatching returns SecKey: " + resultData.debugDescription)
        return resultData!
    } else {
        return resultData!
    }
}

// Finds the SecKeyRef corresponding to the parameter key and returns it as a NSData
private func loadKeyStringFromKeyChainAsNSData(key: String) -> NSData {
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecAttrKeySizeInBits): KEY_SIZE,
        String(kSecClass): kSecClassKey,
        String(kSecAttrApplicationTag): key,
        kSecReturnData as String : kCFBooleanTrue ]

    var dataTypeRef: AnyObject? = nil
    var resultData: NSData? = nil

    let status: OSStatus = withUnsafeMutablePointer(&dataTypeRef) { SecItemCopyMatching(query as NSDictionary, UnsafeMutablePointer($0)) }
    NSLog("SecItemCopyMatching: " + status.description)

    if status == errSecSuccess {
        NSLog("private or public debug description is: " + dataTypeRef.debugDescription)
        resultData = dataTypeRef as? NSData
        return resultData!
    } else {
        NSLog("no key found!!!!")
        return resultData!
    }
}



已编辑



将公钥导出为DER



请注意,此代码不会以DER等可读格式提供publickey

EDITED

Export public key as DER

Note that this code will not provide the publickey in a readable format like DER

let publicKey = loadKeyStringFromKeyChainAsNSData(PUBLIC_KEY + keyId)

如果您需要在iOS之外使用公钥(或导入证书并获取有效密钥),则需要执行额外操作。使用以下项目的 CryptoExportImportManager.swift 支持转换密钥

If you need to use the public key outside iOS (or importing a certificate and obtaining a valid key), extra actions are needed. Converting keys are supported using CryptoExportImportManager.swift of the following project

例如

func exportPublicKeyToDER(keyId:String) -> NSData?{

    let publicKey = loadKeyStringFromKeyChainAsNSData(PUBLIC_KEY + keyId)
    let keyType = kSecAttrKeyTypeRSA
    let keySize = 2048
    let exportImportManager = CryptoExportImportManager()
    if let exportableDERKey = exportImportManager.exportPublicKeyToDER(publicKey, keyType: keyType as String, keySize: keySize) {
        return exportableDERKey
    } else {
        return nil
    }
}

这篇关于在iOS库中生成CSR?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-27 21:43