I am trying to build csr string from publickeyBits and signature from dongle. Below is the swift code portion for generating csr.
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)
let keyDict: [NSString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits: 2048 as Any,
kSecAttrApplicationTag: tagPublic.data(using: .utf8),
]
var error: Unmanaged<CFError>?
let publicKeyFromDongleData = Data.init(base64Encoded: publicKeyFromDongle)
guard let publicKeySecKey = SecKeyCreateWithData(publicKeyFromDongleData! as CFData, keyDict as CFDictionary, &error) else {
print("Failed to create public key:", error!.takeRetainedValue())
return nil
}
let publickeyBits = KeyPairManager.getInstance().getPublicKeyBits(publicKey: publicKeySecKey, enrollmentId: enrollmentId).0
let certificationRequestInfo = buldCertificationRequestInfo(publickeyBits!)
let bytes: [UInt8] = certificationRequestInfo.map { $0 }
let certificationRequestStr = String(decoding: bytes, as: UTF8.self)
let signaturedString = self.dongle?.sign(password: password, data : certificationRequestStr, enrollmentId: enrollmentId)
var signature = [UInt8](repeating: 0, count: 256)
var signatureLen: Int = signature.count
let signatureData = signaturedString!.data(using: .hexadecimal)
signatureData!.copyBytes(to: &signature, count: signatureData!.count)
signatureLen = signatureData!.count
print("signature length: " + String(signatureLen))
print("signature: "+signatureData!.base64EncodedString())
var certificationRequest = Data(capacity: 1024)
certificationRequest.append(certificationRequestInfo)
let shaBytes = keyAlgorithm.sequenceObjectEncryptionType
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
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
}
I wrote a Wrapper where sign function is as of given below. We had a getPublicBits() function here and i think that is working properly. So, I skip this here.
- (NSString*) sign: (NSString*)password data: (NSString*)data enrollmentId: (NSString*)enrollmentId {
Dongle *d = (Dongle*)****;
char * pass = strdup([password UTF8String]);
char * signDataStr = strdup([data UTF8String]);
char * enId = strdup([enrollmentId UTF8String]);
NSData* data2 = [data dataUsingEncoding:NSUTF8StringEncoding];
char *signData = (char *)[data2 bytes];
NSString* signaturedString = [NSString stringWithCString:d->sign(pass, signData, enId).c_str() encoding:[NSString defaultCStringEncoding]];
return signaturedString;
}
I used signUtil method from safenet sdk's library.
std::string Dongle::signUtil(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPrivateKey, char* password, char* data) {
//std::cout<<"data is: " << *data;
CK_RV retCode = CKR_OK;
int isPaddingRequired = 0;
int isDataFromUser = 0;
CK_MECHANISM mech;
CK_BYTE pSigData[3000];
#ifndef PKCS11_V1
CK_ULONG usSigLen = sizeof(pSigData);
#else
CK_ULONG usSigLen = 0;
#endif
char *pInputData = 0;
unsigned long ulInputDataLen = strlen(data);
std::cout << "length: " << ulInputDataLen;
CK_BYTE_PTR pInData = (CK_BYTE_PTR)data;
std::cout << "Mechanism: [6]SHA256-RSA" <<std::endl;
retCode = C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)password, strlen(password));
mech.mechanism = CKM_SHA256_RSA_PKCS;
mech.pParameter = 0;
mech.ulParameterLen = 0;
isDataFromUser = 0;
if( retCode == CKR_OK )
{
if( isPaddingRequired )
{
for(unsigned long ulLoop=ulInputDataLen; ulLoop<64; ++ulLoop)
{
pInData[ulLoop] = 0;
}
ulInputDataLen = 64;
}
}
if (retCode == CKR_OK)
{
retCode = C_SignInit(hSession, &mech, hPrivateKey);
}
CK_ULONG usInLen = (CK_ULONG)ulInputDataLen;
// get the signature length
if(retCode == CKR_OK)
{
retCode = C_Sign(hSession, pInData, usInLen, (CK_BYTE_PTR)NULL_PTR, &usSigLen);
}
// get the signature
if(retCode == CKR_OK)
{
retCode = C_Sign(hSession, pInData, usInLen, (CK_BYTE_PTR)pSigData, &usSigLen);
}
std::string returnSignature = "";
if( (retCode == CKR_OK) && usSigLen )
{
std::cout << "Signed Data " << std::endl << "(hex) ";
for(unsigned long ulLoop=0; ulLoop<usSigLen; ++ulLoop)
{
char pBuffer[25];
sprintf(pBuffer, "%02x", pSigData[ulLoop]);
std::cout << pBuffer;
returnSignature += pBuffer;
}
std::cout << std::endl;
}
// Release memory
if( pInputData )
{
delete pInputData;
}
return returnSignature;
}
I debug a lot and according to csr decoder, only the signature is invalid. public key and signature algorithm are valid.