Giter VIP home page Giter VIP logo

Comments (10)

cbaker6 avatar cbaker6 commented on May 23, 2024

I think it has something to do with how you are creating the keys in keychain. The examples given are for iOS, I believe the process is slightly different macOS. If you create the keys properly then the framework should work.

Issues with generating keys are not issues with this framework

from certificatesigningrequest.

murali238 avatar murali238 commented on May 23, 2024

Thanks.

Able to generate a valid csr if i use SecKeyCopyExternalRepresentation while sending public key bytes to buildcsr function

from certificatesigningrequest.

cbaker6 avatar cbaker6 commented on May 23, 2024

@murali238 thanks for sharing, I will see if I can add your updates into the testcases and readme, unless you see where to add them directly?

from certificatesigningrequest.

murali238 avatar murali238 commented on May 23, 2024

@cbaker6 ,

I have done below two changes on MacOS to generate a valid csr.

  1. kSecAttrApplicationTag key value as Data instead of String
  2. Replaced getPublicKeyBits with below function
 func getPublicKeyBits(_ algorithm: KeyAlgorithm, publicKey: SecKey, tagPublic: String)->(Data?,Int?) {
        
        //Set block size
        let keyBlockSize = SecKeyGetBlockSize(publicKey)
        
        //Ask keychain to provide the publicKey in bits
        let query: [String: AnyObject] = [
            String(kSecClass): kSecClassKey,
            String(kSecAttrKeyType): algorithm.secKeyAttrType,
            String(kSecAttrApplicationTag): tagPublic.data(using: .utf8) as AnyObject,
            String(kSecReturnRef): kCFBooleanTrue
        ]
        var tempPublicKeyBits:AnyObject?
        var _ = SecItemCopyMatching(query as CFDictionary, &tempPublicKeyBits)
        
        if tempPublicKeyBits != nil {
            var error:Unmanaged<CFError>? = nil
            guard let keyBits = SecKeyCopyExternalRepresentation(tempPublicKeyBits as! SecKey, &error) else {
                return (nil,nil)
            }
            return (keyBits as Data,keyBlockSize)
        }
        
        return (nil,nil)
    }

Hope it helps some one.

from certificatesigningrequest.

cbaker6 avatar cbaker6 commented on May 23, 2024

@murali238 I've added your recommendations, but for some reason the keys don't generate when I run the tests, swift test from command line.

Was there anything else you added?

The changes I made are here

func getPublicKeyBits(_ algorithm: KeyAlgorithm, publicKey: SecKey, tagPublic: String)->(Data?,Int?) {
//Set block size
let keyBlockSize = SecKeyGetBlockSize(publicKey)
//Ask keychain to provide the publicKey in bits
var query: [String: AnyObject] = [
String(kSecClass): kSecClassKey,
String(kSecAttrKeyType): algorithm.secKeyAttrType,
String(kSecReturnData): kCFBooleanTrue
]
if #available(iOS 11, *) {
query[String(kSecAttrApplicationTag)] = tagPublic as AnyObject
} else {
query[String(kSecAttrApplicationTag)] = tagPublic.data(using: .utf8) as AnyObject
}
var tempPublicKeyBits:CFTypeRef?
var _ = SecItemCopyMatching(query as CFDictionary, &tempPublicKeyBits)
let returnKeyBits: Data!
if #available(iOS 11, *) {
guard let keyBits = tempPublicKeyBits as? Data else {
return (nil,nil)
}
returnKeyBits = keyBits
} else {
var error:Unmanaged<CFError>? = nil
guard let keyBits = SecKeyCopyExternalRepresentation(tempPublicKeyBits as! SecKey, &error), error != nil else {
print("Error in CertificateSigningRequestTests.getPublicKeyBits(). \(error!)")
return (nil,nil)
}
returnKeyBits = keyBits as Data
}
return (returnKeyBits,keyBlockSize)
}

from certificatesigningrequest.

murali238 avatar murali238 commented on May 23, 2024

@cbaker6
inside getPublicKeyBits function, instead of String(kSecReturnData): kCFBooleanTrue , Please use String(kSecReturnRef): kCFBooleanTrue in the query on macOS (kSecReturnData is fine on iOS)

from certificatesigningrequest.

cbaker6 avatar cbaker6 commented on May 23, 2024

I tried out your getPublicKeyBits function, but I still got the same errors.

Did you do anything different when creating the keys besides using query[String(kSecAttrApplicationTag)] = tagPublic.data(using: .utf8) as AnyObject?

The updated function I have is below:

func getPublicKeyBits(_ algorithm: KeyAlgorithm, publicKey: SecKey, tagPublic: String)->(Data?,Int?) {
//Set block size
let keyBlockSize = SecKeyGetBlockSize(publicKey)
//Ask keychain to provide the publicKey in bits
var query: [String: AnyObject] = [
String(kSecClass): kSecClassKey,
String(kSecAttrKeyType): algorithm.secKeyAttrType,
]
if #available(iOS 11, *) {
query[String(kSecReturnData)] = kCFBooleanTrue
query[String(kSecAttrApplicationTag)] = tagPublic as AnyObject
} else {
query[String(kSecReturnRef)] = kCFBooleanTrue
query[String(kSecAttrApplicationTag)] = tagPublic.data(using: .utf8) as AnyObject
}
var tempPublicKeyBits:CFTypeRef?
var _ = SecItemCopyMatching(query as CFDictionary, &tempPublicKeyBits)
let returnKeyBits: Data!
if #available(iOS 11, *) {
guard let keyBits = tempPublicKeyBits as? Data else {
return (nil,nil)
}
returnKeyBits = keyBits
} else {
var error:Unmanaged<CFError>? = nil
guard let keyBits = SecKeyCopyExternalRepresentation(tempPublicKeyBits as! SecKey, &error), error != nil else {
print("Error in CertificateSigningRequestTests.getPublicKeyBits(). \(String(describing: error))")
return (nil,nil)
}
returnKeyBits = keyBits as Data
}
return (returnKeyBits,keyBlockSize)
}

The code to create the keys is below:

func generateKeysAndStoreInKeychain(_ algorithm: KeyAlgorithm, keySize: Int, tagPrivate: String, tagPublic: String)->(SecKey?,SecKey?){
var publicKeyParameters: [String: AnyObject] = [
String(kSecAttrIsPermanent): kCFBooleanTrue,
String(kSecAttrAccessible): kSecAttrAccessibleAfterFirstUnlock
]
var privateKeyParameters: [String: AnyObject] = [
String(kSecAttrIsPermanent): kCFBooleanTrue,
String(kSecAttrAccessible): kSecAttrAccessibleAfterFirstUnlock
]
if #available(iOS 11, *) {
publicKeyParameters[String(kSecAttrApplicationTag)] = tagPublic as AnyObject
privateKeyParameters[String(kSecAttrApplicationTag)] = tagPrivate as AnyObject
} else {
publicKeyParameters[String(kSecAttrApplicationTag)] = tagPublic.data(using: .utf8) as AnyObject
privateKeyParameters[String(kSecAttrApplicationTag)] = tagPrivate.data(using: .utf8) as AnyObject
}

from certificatesigningrequest.

cbaker6 avatar cbaker6 commented on May 23, 2024

@murali238 you can see the errors in GitHub Actions here under "Build": https://github.com/cbaker6/CertificateSigningRequest/runs/1043401059?check_suite_focus=true

The error code is -25300, Error Domain=NSOSStatusErrorDomain Code=-50 "failed to generate asymmetric keypair" (paramErr: error in user parameter list) UserInfo={NSDescription=failed to generate asymmetric keypair}, keys weren't created

from certificatesigningrequest.

cbaker6 avatar cbaker6 commented on May 23, 2024

It turns out if the keychain parameters are switched to [String: Any], the only thing that needs to be fixed is String(kSecAttrApplicationTag): tagPublic.data(using: .utf8)!

This allows interoperability between iOS and macOS.

See the updates here:

func getPublicKeyBits(_ algorithm: KeyAlgorithm, publicKey: SecKey, tagPublic: String)->(Data?,Int?) {
//Set block size
let keyBlockSize = SecKeyGetBlockSize(publicKey)
//Ask keychain to provide the publicKey in bits
let query: [String: Any] = [
String(kSecClass): kSecClassKey,
String(kSecAttrKeyType): algorithm.secKeyAttrType,
String(kSecAttrApplicationTag): tagPublic.data(using: .utf8)!,
String(kSecReturnData): true
]
var tempPublicKeyBits:CFTypeRef?
var _ = SecItemCopyMatching(query as CFDictionary, &tempPublicKeyBits)
guard let keyBits = tempPublicKeyBits as? Data else {
return (nil,nil)
}
return (keyBits,keyBlockSize)
}

from certificatesigningrequest.

stklieme avatar stklieme commented on May 23, 2024

@murali238, thank you so much. I ran into the same problem on macOS and looked for a solution for weeks.
The SecKeyCopyExternalRepresentation way solved it.

@cbaker6 By the way you can get rid of all the String conversions by bridge casting the type rather than annotating it.
For example

      let query = [ 
             kSecClass: kSecClassKey, 
             kSecAttrKeyType: algorithm.secKeyAttrType, 
             kSecAttrApplicationTag: tagPublic.data(using: .utf8)!, 
             kSecReturnData: true 
         ] as [String:Any]

from certificatesigningrequest.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.