Converting SHA1 string encryption code from objective-c to swift

228 Views Asked by At

So this is the original Objective-C code I have:

- (NSString *)calculateSignaturewithAPIKey:(NSString *)apiKey apiKeyPrivate:(NSString *)apiKeyPrivate httpMethod:(NSString *)httpMethod route:(NSString *)theRoute andExpiresIn:(NSString *)expireTime {
    NSString *string_to_sign = [NSString stringWithFormat:@"%@:%@:%@:%@",apiKey,httpMethod,theRoute,expireTime];

    const char *cKey  = [apiKeyPrivate cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [string_to_sign cStringUsingEncoding:NSASCIIStringEncoding];

    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];

    NSString *signature = [HMAC base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    return signature;
}

In Swift 3 I managed to get as far as:

func calculateSignature(withPublicApiKey publicApiKey: String, andApiPrivateKey privateApiKey: String, withHttpMethod httpMethod: String, andRoute route: String, exiresIn expireTime: String) -> String {
    let string_to_sign = "\(publicApiKey):\(httpMethod):\(route):\(expireTime)"

    let cKey = privateApiKey.cString(using: String.Encoding.ascii)
    let cData = Data.base64EncodedString(Data.init)

    var cHMAC = [CUnsignedChar](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))

But I don't know how to proceed here. I have been able to import Crypto related things into my Swift project. Please assist.

1

There are 1 best solutions below

1
On BEST ANSWER

Try this:

func calculateSignature(withPublicApiKey publicApiKey: String, andApiPrivateKey privateApiKey: String, withHttpMethod httpMethod: String, andRoute route: String, exiresIn expireTime: String) -> String {
    let string_to_sign = "\(publicApiKey):\(httpMethod):\(route):\(expireTime)"
    let cKey = privateApiKey.cString(using: .ascii)!
    let cData = string_to_sign.cString(using: .ascii)!

    var cHMAC = [CUnsignedChar](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
    CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), cKey, cKey.count - 1, cData, cData.count - 1, &cHMAC)

    let HMAC = Data(bytes: &cHMAC, count: Int(CC_SHA1_DIGEST_LENGTH))
    return HMAC.base64EncodedString(options: .lineLength64Characters)
}

My personal experience is that Swift really hates pointers. If you code makes heavy use of pointer, it's easer to write them in C/ObjC.