在iOS上解决EC签名验证失败(ccer-7)的任何帮助

在iOS上解决EC签名验证失败(ccer-7)的任何帮助,ios,security,Ios,Security,我正在尝试在iOS平台上创建签名验证,以验证签名和公钥是否已知。我们的目标是创建类似于Android的Signature类的东西,将密钥、未签名实体中的一些字节和已知签名传递到其中,然后调用verify(),它将告诉您签名是否有效。 公钥字符串是已知的,并且是base64编码的。签名也是已知的,并且是base64编码的。我知道加密的算法是ECSHA256。当我创建公钥时,它是65字节,以4开头。我对签名也有100%的把握,我比较了iOS和Android上签名的字节数组。它们是一样的,但安卓似乎验

我正在尝试在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
}