I have created public key and private key in my smartcard(Dongle) using safenet sdk's own library. I realized that Both are in PKCS#8 format. Both Private key and Public Key starts with "BEGIN PUBLIC KEY" and "BEGIN PRIVATE KEY" instead of "BEGIN RSA PUBLIC KEY" and "BEGIN RSA PRIVATE KEY".
I also signed CertificationInfo's(ex: Distinguished Names such as common name, postal code etc.). Then I am sending PubLic Key and the signed Data to my swift application to generate csr.
In csr generation step, I converted the public key to rsa format by removing first 32 characters, then convert it to SecKey to generate csr. I found that, after extracting seckey to Data, it is same before and after the SecKey conversion.
But, when i validate the signature with public key, It says that "Signature is invalid". Is it because the public key is in PKCS#1 format and the private key by whom the CertificationInfo is signed is in PKCS#8 format?
If this is the reason, what will be the probable fix to resolve the issue? Do i need to convert the Key format in native end(using C code)? What is the mechanism of generating PKCS#1 format key in C? Or, Is there any way to generate PKCS#8 SecKey using swift?
My csr generation code is below
public func buildCSRAndReturnStringUsingDongle(enrollmentId: String, password: String) -> String? {
let tagPublic = "public" + enrollmentId
self.dongle = DongleManager.getInstance()
self.dongle?.generateKeyPair(enrollmentId: enrollmentId, password: password)
let publicKeyFromDongle: String = (self.dongle?.getPublicKeyBits(enrollmentId: enrollmentId, password: password))!
print("Public Key is: \n",publicKeyFromDongle.dropFirst(32))
let keyDict: [NSString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPublic,
kSecAttrApplicationTag: tagPublic.data(using: .utf8),
]
var error: Unmanaged<CFError>?
let publicKeyFromDongleEncodedData = publicKeyFromDongle.dropFirst(32).data(using: .utf8)!
let publicKeyFromDongleData = Data(base64Encoded: publicKeyFromDongleEncodedData)
guard let publicKeySecKey = SecKeyCreateWithData(publicKeyFromDongleData! as CFData, keyDict as CFDictionary, &error) else {
print("Failed to create public key:", error!.takeRetainedValue())
return nil
}
//var error:Unmanaged<CFError>?
if let cfdata = SecKeyCopyExternalRepresentation(publicKeySecKey, &error) {
let data:Data = cfdata as Data
let b64Key = data.base64EncodedString()
print("after : \n")
print(b64Key)
}
let publickeyBits = KeyPairManager.getInstance().getPublicKeyBits(publicKey: publicKeySecKey, enrollmentId: enrollmentId).0!
print("public key bits conversion: \n");
print(publickeyBits)
// let publickeyBits = publicKeyFromDongle.data(using: String.Encoding(rawValue: NSASCIIStringEncoding)) as! CFData as Data
let publickeyBitss = publicKeyFromDongleData as! CFData as Data
print("public key 64: \n")
print(publickeyBitss)
let certificationRequestInfo = buldCertificationRequestInfo(publickeyBits)
let bytes: [UInt8] = certificationRequestInfo.map { $0 }
let certificationRequestStr = String(decoding: bytes, as: UTF8.self)
let signaturedStringData = self.dongle?.signn(password: password, data : certificationRequestInfo as CFData, enrollmentId: enrollmentId)
print("signatured string with data: \n")
print(signaturedStringData)
var signature = [UInt8](repeating: 0, count: 256)
var signatureLen: Int = signature.count
let signatureData = signaturedStringData!.data(using: .hexadecimal)
signatureData!.copyBytes(to: &signature, count: signatureData!.count)
if let string = String(bytes: signature, encoding: .utf8) {
print(string)
} else {
print("not a valid UTF-8 sequence")
}
signatureLen = signatureData!.count
print("signature length: " + String(signatureLen))
print("signature: "+signatureData!.base64EncodedString())
var certificationRequest = Data(capacity: 1024)
certificationRequest.append(certificationRequestInfo)
let shaBytes = keyAlgorithm.sequenceObjectEncryptionType
print("shaBytes are \n");
print(shaBytes)
certificationRequest.append(shaBytes, count: shaBytes.count)
var signData = Data(capacity: 2049)
let zero: UInt8 = 0 // Prepend zero
signData.append(zero)
signData.append(signature, count: signatureLen)
appendBITSTRING(signData, into: &certificationRequest)
enclose(&certificationRequest, by: sequenceTag) // Enclose into SEQUENCE
//print("certification request: "+certificationRequest.base64EncodedString())
let csrString = certificationRequest.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
print(csrString)
let head = "-----BEGIN CERTIFICATE REQUEST-----\n"
let foot = "-----END CERTIFICATE REQUEST-----\n"
var isMultiple = false
var newCSRString = head
//Check if string size is a multiple of 64
if csrString!.count % 64 == 0 {
isMultiple = true
}
for (integer, character) in csrString!.enumerated() {
newCSRString.append(character)
if (integer != 0) && ((integer + 1) % 64 == 0) {
newCSRString.append("\n")
}
if (integer == csrString!.count-1) && !isMultiple {
newCSRString.append("\n")
}
}
newCSRString += foot
return newCSRString
}