Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crspybits/d8d34d18a08eab57c62a0b30f64c4f64 to your computer and use it in GitHub Desktop.
Save crspybits/d8d34d18a08eab57c62a0b30f64c4f64 to your computer and use it in GitHub Desktop.
Cloudinary signature generation, in Swift-- using the CryptoSwift Cocoapod for SHA1 hash.
/* Experimenting with creating a signature to make it easier to do the server-side development.
See https://github.com/cloudinary/cloudinary_java/blob/master/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java#L129
and https://support.cloudinary.com/hc/en-us/articles/203817991-How-to-generate-a-Cloudinary-signature-on-my-own-
*/
// The optional timestamp is for testing this method-- this should be a UNIX timestamp with no trailing decimals-- i.e., just an integer number.
// Don't use "public_id" or "timestamp" as keys in otherParams if you give it.
func createSignature(publicId: String, apiSecret: String, otherParams: [String: Any]? = nil, timestamp: String? = nil) -> (signature: String, timestamp: String)? {
// 1) Set up the parameters we're going to use in the signing.
var params = [String: Any]()
if let otherParams = otherParams {
for (key, value) in otherParams {
params[key] = value
}
}
params["public_id"] = publicId
// "UNIX" timestamp
if let timestamp = timestamp {
params["timestamp"] = timestamp
} else {
params["timestamp"] = "\(Int(Date().timeIntervalSince1970))"
}
// 2) Sort the keys-- Cloudinary relies on the keys being sorted in ascending order before generating the signature.
let sortedKeys = params.keys.sorted(by: <)
var toSign:String = ""
// 3) Set up the key=value pairs, with intervening "&" between pairs, for signing
for key in sortedKeys {
if toSign.length > 0 {
toSign += "&"
}
let value = params[key]!
toSign += "\(key)=\(value)"
}
// 4) Cloudinary signature generation relies on the secret being appended to this sequence of key value pairs.
toSign += apiSecret
guard let toSignData = toSign.data(using: .utf8) else {
Log.error("Failed converting string to data.")
return nil
}
// 5) Generate the SHA1 hash.
let signedData = toSignData.sha1()
return (signedData.toHexString(), params["timestamp"] as! String)
}
func testSignatureCreation() {
/* From: https://support.cloudinary.com/hc/en-us/articles/203817991-How-to-generate-a-Cloudinary-signature-on-my-own-
Sanity check - Signing the following string:
"public_id=sample_image&timestamp=1315060510abcd"
where `abcd` is the api_secret, should result with the following signature:
"b4ad47fb4e25c7bf5f92a20089f9db59bc302313"
*/
let expectedResult = "b4ad47fb4e25c7bf5f92a20089f9db59bc302313"
guard let (signature, _) = createSignature(publicId: "sample_image", apiSecret: "abcd", timestamp: "1315060510") else {
XCTFail()
return
}
XCTAssert(expectedResult == signature)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment