Your code does not produce the expected result because the
referenced md5()
function returns the message digest as a
hex-encoded string, which is then Base64 encoded. So instead of
String -> UTF-8 data -> MD5 digest -> Base64 encoding
you are doing
String -> UTF-8 data -> MD5 digest -> hex encoding -> Base64 encoding
A small modification of the function returns the message digest
as data:
func md5(string string: String) -> NSData {
var digest = [UInt8](count: Int(CC_MD5_DIGEST_LENGTH), repeatedValue: 0)
let data = string.dataUsingEncoding(NSUTF8StringEncoding)! // Conversion to UTF-8 cannot fail
CC_MD5(data.bytes, CC_LONG(data.length), &digest)
return NSData(bytes: digest, length: digest.count)
}
Now you can compute the Base 64 encoded MD5 digest:
let string = "Hello World"
// Compute MD5 message digest:
let md5data = md5(string: string)
print("md5data = \(md5data)") // md5data = <b10a8db1 64e07541 05b7a99b e72e3fe5>
// Convert to Base 64 encoded string:
let base64 = md5data.base64EncodedStringWithOptions([])
print("base64 = \(base64)") // base64 = sQqNsWTgdUEFt6mb5y4/5Q==
This is almost what you expect. The Java code apparently produces
the so-called "base64url" variant without padding
(compare https://en.wikipedia.org/wiki/Base64#Variants_summary_table).
Therefore we have to modify two characters and remove the padding:
let base64url = base64
.stringByReplacingOccurrencesOfString("+", withString: "-")
.stringByReplacingOccurrencesOfString("/", withString: "_")
.stringByReplacingOccurrencesOfString("=", withString: "")
print("base64url = \(base64url)") // base64url = sQqNsWTgdUEFt6mb5y4_5Q
Now the result is sQqNsWTgdUEFt6mb5y4_5Q
, and identical to what
you got from the Java code.