在iOS上解决EC签名验证失败(ccer-7)的任何帮助
我正在尝试在iOS平台上创建签名验证,以验证签名和公钥是否已知。我们的目标是创建类似于Android的Signature类的东西,将密钥、未签名实体中的一些字节和已知签名传递到其中,然后调用verify(),它将告诉您签名是否有效。 公钥字符串是已知的,并且是base64编码的。签名也是已知的,并且是base64编码的。我知道加密的算法是ECSHA256。当我创建公钥时,它是65字节,以4开头。我对签名也有100%的把握,我比较了iOS和Android上签名的字节数组。它们是一样的,但安卓似乎验证了签名。 我正在粘贴我正在做的代码。如果有人能指出我做错了什么,那就太好了。 谢谢在iOS上解决EC签名验证失败(ccer-7)的任何帮助,ios,security,Ios,Security,我正在尝试在iOS平台上创建签名验证,以验证签名和公钥是否已知。我们的目标是创建类似于Android的Signature类的东西,将密钥、未签名实体中的一些字节和已知签名传递到其中,然后调用verify(),它将告诉您签名是否有效。 公钥字符串是已知的,并且是base64编码的。签名也是已知的,并且是base64编码的。我知道加密的算法是ECSHA256。当我创建公钥时,它是65字节,以4开头。我对签名也有100%的把握,我比较了iOS和Android上签名的字节数组。它们是一样的,但安卓似乎验
private-var-algorithm:SecKeyAlgorithm=.ecdsaSignatureMessageX962SHA256
typealias SecKeyPair=(公钥:SecKey?,私钥:SecKey?)
/**
使用256位椭圆曲线签名生成公钥
(256位EC公钥长度为65字节,以04开头。)
*/
func getPublicKey(keyAsBytes:[UInt8])->SecKeyPair{
设keyType=ksecAttrkeyTypecSecPrimeRandom
让keySize=256
让privateKeyParams:[String:AnyObject]=[kSecAttrIsPermanent as String:false as AnyObject,
kSecAttrApplicationTag作为字符串:keyAsBytes作为任意对象]
让publicKeyParams:[String:AnyObject]=[kSecAttrIsPermanent as String:false as AnyObject,
kSecAttrApplicationTag作为字符串:keyAsBytes作为任意对象]
let参数:[String:AnyObject]=[kSecAttrKeyType作为String:keyType,
kSecAttrKeySizeInBits as String:keySize as AnyObject,
kSecPublicKeyAttrs作为字符串:publicKeyParams作为任何对象,
kSecPrivateKeyAttrs作为字符串:privateKeyParams作为任何对象]
var publicKey,privateKey:SecKey?
_=SecKeyGeneratePair(参数为CFDictionary、&publicKey和&privateKey)
返回SecKeyPair(公钥:公钥,私钥:私钥)
}
私有函数验证原始(公钥:SecKey,
updatePackage:数据,
签名:Data)->Bool{
//#定义CC_SHA256_摘要_长度32
//创建包含32个零的无符号8位整数数组
变量摘要=[UInt8](重复:0,计数:Int(抄送摘要长度))
//CC_SHA256执行摘要计算并将结果放入调用者提供的摘要缓冲区(md)
_=updatePackage.withUnsafeBytes{
CC_SHA256($0.baseAddress,UInt32(updatePackage.count)和摘要)
}
让结果=SecKeyRawVerify(公钥,
.PKCS1SHA256,
消化,
伯爵阁下,
signature.bytes,
signature.bytes.count)
返回结果==errSecSuccess
}
专用功能验证(公钥:SecKey,
更新包:CFData,
签名:CFData,
私钥:SecKey?=nil)->Bool{
var结果=错误
PBVAR错误:非托管?
变量摘要=[UInt8](重复:0,计数:Int(抄送摘要长度))
//CC_SHA256执行摘要计算并将结果放入调用者提供的摘要缓冲区(md)
let data=(更新打包为数据)
_=data.withUnsafeBytes{
CC_SHA256($0.0.baseAddress、UInt32(data.count)和摘要)
}
让digestAsData=Data(字节:digest,计数:digest.count)
如果加密验证签名(公钥,
算法,
digestAsData作为CFData,
签名,
&pbError){
结果=真
}否则{
Log.error(消息:“[F_MANAGER]无法验证签名\(pbError!.takeRetainedValue()作为错误)”)
}
返回结果
}
私有函数isSignatureValid(更新包:[UInt8],解码签名字节:[UInt8],公钥:字符串)->Bool{
var结果=错误
//生成公钥
如果let decodedKey=Data(base64Encoded:publicKey){
let keys=getPublicKey(keyAsBytes:decodedKey.bytes)
如果让pKey=keys.publicKey{
设decodedSignature=数据(decodedSignatureBytes)
让canVerify=seckeyisalgorithsupported(pKey、.verify、algorithm)
如果可以验证{
让doRaw=假
让updatePackageAsData=Data(updatePackage)
如果多劳{
结果=验证原始数据(公钥:pKey,
updatePackage:updatePackageAsData,
签名:解码(签名)
如果!结果{
让b64EncodedPackageAsData=updatePackageAsData.base64EncodedData()
结果=验证原始数据(公钥:pKey,
updatePackage:b64EncodedPackageAsData,
签名:解码(签名)
}
}否则{
结果=验证(公钥:pKey,
updatePackage:updatePackageAsData作为CFData,
签名:解码签名为CFData)
如果!结果{
让b64EncodedPackageAsData=updatePackageAsData.base64EncodedData()
结果=验证(公钥:pKey,
更新包:b64En
private var algorithm: SecKeyAlgorithm = .ecdsaSignatureMessageX962SHA256
typealias SecKeyPair = (publicKey: SecKey?, privateKey: SecKey?)
/**
Generates a public key using the 256 bit Elliptic Curve Signature
(a 256 bit EC public key is 65 bytes long and starts with an 04.)
*/
func getPublicKey(keyAsBytes: [UInt8]) -> SecKeyPair {
let keyType = kSecAttrKeyTypeECSECPrimeRandom
let keySize = 256
let privateKeyParams: [String: AnyObject] = [kSecAttrIsPermanent as String: false as AnyObject,
kSecAttrApplicationTag as String: keyAsBytes as AnyObject]
let publicKeyParams: [String: AnyObject] = [kSecAttrIsPermanent as String: false as AnyObject,
kSecAttrApplicationTag as String: keyAsBytes as AnyObject]
let parameters: [String: AnyObject] = [kSecAttrKeyType as String: keyType,
kSecAttrKeySizeInBits as String: keySize as AnyObject,
kSecPublicKeyAttrs as String: publicKeyParams as AnyObject,
kSecPrivateKeyAttrs as String: privateKeyParams as AnyObject]
var publicKey, privateKey: SecKey?
_ = SecKeyGeneratePair(parameters as CFDictionary, &publicKey, &privateKey)
return SecKeyPair(publicKey: publicKey, privateKey: privateKey)
}
private func verifyRaw(publicKey: SecKey,
updatePackage: Data,
signature: Data) -> Bool {
// #define CC_SHA256_DIGEST_LENGTH 32
// Creates an array of unsigned 8 bit integers that contains 32 zeros
var digest = [UInt8](repeating: 0, count:Int(CC_SHA256_DIGEST_LENGTH))
// CC_SHA256 performs digest calculation and places the result in the caller-supplied buffer for digest (md)
_ = updatePackage.withUnsafeBytes {
CC_SHA256($0.baseAddress, UInt32(updatePackage.count), &digest)
}
let result = SecKeyRawVerify(publicKey,
.PKCS1SHA256,
digest,
digest.count,
signature.bytes,
signature.bytes.count)
return result == errSecSuccess
}
private func verify(publicKey: SecKey,
updatePackage: CFData,
signature: CFData,
privateKey: SecKey? = nil) -> Bool {
var result = false
var pbError:Unmanaged<CFError>?
var digest = [UInt8](repeating: 0, count:Int(CC_SHA256_DIGEST_LENGTH))
// CC_SHA256 performs digest calculation and places the result in the caller-supplied buffer for digest (md)
let data = (updatePackage as Data)
_ = data.withUnsafeBytes {
CC_SHA256($0.baseAddress, UInt32(data.count), &digest)
}
let digestAsData = Data(bytes: digest, count: digest.count)
if SecKeyVerifySignature(publicKey,
algorithm,
digestAsData as CFData,
signature,
&pbError) {
result = true
} else {
Log.error(message: "[F_MANAGER] Unable to verify signature \(pbError!.takeRetainedValue() as Error)")
}
return result
}
private func isSignatureValid(updatePackage: [UInt8], decodedSignatureBytes: [UInt8], publicKey: String) -> Bool {
var result = false
// Generate the Public Key key
if let decodedKey = Data(base64Encoded: publicKey) {
let keys = getPublicKey(keyAsBytes: decodedKey.bytes)
if let pKey = keys.publicKey {
let decodedSignature = Data(decodedSignatureBytes)
let canVerify = SecKeyIsAlgorithmSupported(pKey, .verify, algorithm)
if canVerify {
let doRaw = false
let updatePackageAsData = Data(updatePackage)
if doRaw {
result = verifyRaw(publicKey: pKey,
updatePackage: updatePackageAsData,
signature: decodedSignature)
if !result {
let b64EncodedPackageAsData = updatePackageAsData.base64EncodedData()
result = verifyRaw(publicKey: pKey,
updatePackage: b64EncodedPackageAsData,
signature: decodedSignature)
}
} else {
result = verify(publicKey: pKey,
updatePackage: updatePackageAsData as CFData,
signature: decodedSignature as CFData)
if !result {
let b64EncodedPackageAsData = updatePackageAsData.base64EncodedData()
result = verify(publicKey: pKey,
updatePackage: b64EncodedPackageAsData as CFData,
signature: decodedSignature as CFData)
}
}
} else {
Log.error(message: "[F_MANAGER] Algorithm not supported")
}
}
}
return result
}
@available(iOS 14.0, *)
private func verifySignature(data: Data, key: Data, signature: Data) -> Bool {
var result = false
do {
let publicKey = try P384.Signing.PublicKey(derRepresentation: key.bytes)
let hash = SHA256.hash(data: data)
let signing384 = try P384.Signing.ECDSASignature(derRepresentation: signature)
if publicKey.isValidSignature(signing384, for: hash) {
result = true
}
} catch {
Log.error(message: "[F_MANAGER] Exception \(error)")
}
return result
}