iOS

iOS Security Framework 的签名和验证

Posted by 你看那朵乌云儿 on January 28, 2019

Overview

为了在数据块上创建加密签名,首先要创建数据的散列,也就是对数据进行 hash 算法,这样就得到了数据的摘要,然后使用私钥加密此摘要,这样就得到了数据的签名。接收方使用您的公钥解密签名,同时独立地重新创建原始数据的散列(哈希)。如果解密后的哈希与计算出的哈希匹配,则接收方可以确保数据来自与公钥对应的私钥的所有者。

通常,将数据块签名作为执行其他操作的附属工作。例如,作为发布应用程序的最后一步,Xcode 使用你的一个密码身份代表你对代码进行签名。

私钥

首先,签名算法需要一个私钥,这个私钥是非对称加密密码对的私钥部分。私钥的格式一般有 DER 和 PEM。下面的代码是从 PEM 格式的文件得到一个私钥:

static func getPrivateKeyFromFile() throws -> Data {
	let priPath = Bundle.main.path(forResource: "pri", ofType: ".key")!
	let priUrl = URL(fileURLWithPath: priPath)
	guard var priString = try? String(contentsOf: priUrl) else {
		throw PaymentError.privateKeyLoadFailed
	}
	let beginRange = priString.range(of: "-----BEGIN RSA PRIVATE KEY-----")!
	priString.removeSubrange(beginRange)		let endRange = priString.range(of: "-----END RSA PRIVATE KEY-----")!
		priString.removeSubrange(endRange)
		priString.removeAll { (c) -> Bool in
		c == "\n"
	}
	let decodedData = Data(base64Encoded: priString)!
	return decodedData
}

签名

使用 Security Framework 对数据进去签名

// 指定签名算法
let algorithm = SecKeyAlgorithm.rsaSignatureMessagePKCS1v15SHA256

// 错误处理
var error: Unmanaged<CFError>?

// 签名算法选项
let options: [String: Any] = [kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
                                  kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
                                  kSecAttrKeySizeInBits as String: 2048]

// 私钥
let cfKey = getPrivateKeyFromFile() as CFData
    
guard let secKey = SecKeyCreateWithData(cfKey, options as CFDictionary, &error) else {
		print(error as Any)
		throw PaymentError.privateKeyLoadFailed
}
guard let signature = SecKeyCreateSignature(secKey, algorithm, requestData as CFData, &error) as Data? else {
	throw XXXXError
}

签名验证

成功生成签名后,将数据和签名发送给任何相关方。然后使用您的公钥,收件人通过执行一组类似于签名过程的操作来验证签名。

var error: Unmanaged<CFError>?
guard SecKeyVerifySignature(publicKey, algorithm, data as CFData, signature as CFData, &error) else {
	throw error!.takeRetainedValue() as Error
}

其他

我发现 Swift 中使用 Core Foundation 的 API 已经不再需要手动执行 release 啦。
哈哈哈。。。 真是开心啊