2017-02-22 9 views
0

私は、Ecliptic Curveキー(256ビット)のセットを生成するプロトタイプを書き、プライベートキーを使用してメッセージに署名します。私はコードを生成し、うまく動作するキーを管理していますが、私はSecKeyRawSignを呼び出そうとすると、-50のerrSecParamエラーが発生します。署名にSecKeyRawSignは、ECキーで署名するときに-50を返します

private func generateKeyPair() throws { 
    var error: Unmanaged<CFError>? = nil 
    let acl = SecAccessControlCreateWithFlags(nil, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, 
               [.touchIDAny, .privateKeyUsage], &error) 

    guard error == nil else { 
     throw MessageError(message: "Could not create ACL: \(error)") 
    } 

    // We don't want the public key stored in the ecure enclave, so we create it as 
    // non permament and add it manually to the keychain later 
    let publicKeyParameters: [CFString: Any] = [ 
     kSecAttrIsPermanent: false, 
     kSecAttrApplicationTag: ViewController.KeyTag, 
     kSecAttrLabel: ViewController.PublicLabel 
    ] 

    let privateKeyParameters: [CFString: Any] = [ 
     kSecAttrIsPermanent: true, 
     kSecAttrApplicationTag: ViewController.KeyTag, 
     kSecAttrLabel: ViewController.PrivateLabel, 
     kSecAttrAccessControl: acl! 
    ] 

    var parameters: [CFString: Any] = [ 
     kSecAttrKeyType: kSecAttrKeyTypeEC, 
     kSecAttrKeySizeInBits: NSNumber(value: 256), 
     kSecPublicKeyAttrs: publicKeyParameters, 
     kSecPrivateKeyAttrs: privateKeyParameters 
    ] 

    // On the simulator we can't use the Secure Enclave 
    if hasSecureEnclave() { 
     parameters[kSecAttrTokenID] = kSecAttrTokenIDSecureEnclave 
    } 

    var pubKeyRef, privKeyRef: SecKey? 
    var result = SecKeyGeneratePair(parameters as CFDictionary, &pubKeyRef, &privKeyRef) 
    guard result == noErr else { 
     throw MessageError(message: "Could not create key pair: \(result)") 
    } 

    parameters = [ 
     kSecClass: kSecClassKey, 
     kSecAttrKeyType: kSecAttrKeyTypeEC, 
     kSecAttrApplicationTag: ViewController.KeyTag, 
     kSecAttrLabel: ViewController.PublicLabel, 
     kSecAttrKeyClass: kSecAttrKeyClassPublic, 
     kSecValueRef: pubKeyRef! 
    ] 

    result = SecItemAdd(parameters as CFDictionary, nil) 
    guard result == noErr else { 
     throw MessageError(message: "Could not add public key to keychain: \(result)") 
    } 
} 

コード次のようになります:キーを生成するコードは次のようになります

private func signWithPrivateKey(_ text: String, _ key: SecKey) throws -> String? { 
    var digest = Data(count: Int(CC_SHA256_DIGEST_LENGTH)) 
    let data = text.data(using: .utf8)! 

    let _ = digest.withUnsafeMutableBytes { digestBytes in 
     data.withUnsafeBytes { dataBytes in 
      CC_SHA256(dataBytes, CC_LONG(data.count), digestBytes) 
     } 
    } 

    var signature = Data(count: SecKeyGetBlockSize(key)) 
    var signatureLength = signature.count 

    let result = signature.withUnsafeMutableBytes { signatureBytes in 
     digest.withUnsafeBytes { digestBytes in 
      SecKeyRawSign(key, 
          SecPadding.PKCS1SHA256, 
          digestBytes, 
          digest.count, 
          signatureBytes, 
          &signatureLength) 
     } 
    } 

    guard result == noErr else { 
     throw MessageError(message: "Could not sign data: \(result)") 
    } 

    return signature.base64EncodedString() 
} 

明らか符号関数の最後のガードが作動している、そしてそれはerrSecParamを返します。

誰かがECキーを使用してiOSでデータ署名に成功しましたか?もしそうなら、あなたはここで何か分かりますか?接線的に、エラーそのものに関するより多くの情報を得る方法があります。

編集:重要な詳細を追加するには、このコードを変更して2048ビットのRSAキーを生成する以外は何もしないと、コードは正常に動作します。キーが生成され、メッセージに署名が付けられます。失敗するのは256ビットのECキーだけです。 iOSでECDSAを実行するための代替方法がありますか?

答えて

0

私はこれを解決しました。署名を保持するために作成していたバッファーが小さすぎました。私はSecKeyGetBlockSize()* 4を使用するように変更し、呼び出し後にバッファをsignatureLenghtに減らしました。この時点で私の唯一の問題は、長さを把握するより良い方法がある場合です(SecKeyRawSignを呼び出すこと、失敗させ、バッファサイズを返されたサイズに調整すること以外)。

新しいサインのコードは次のようになります。

private func signWithPrivateKey(_ text: String, _ key: SecKey) throws -> String? { 
    var digest = Data(count: Int(CC_SHA256_DIGEST_LENGTH)) 
    let data = text.data(using: .utf8)! 

    let _ = digest.withUnsafeMutableBytes { digestBytes in 
     data.withUnsafeBytes { dataBytes in 
      CC_SHA256(dataBytes, CC_LONG(data.count), digestBytes) 
     } 
    } 

    var signature = Data(count: SecKeyGetBlockSize(key) * 4) 
    var signatureLength = signature.count 

    let result = signature.withUnsafeMutableBytes { signatureBytes in 
     digest.withUnsafeBytes { digestBytes in 
      SecKeyRawSign(key, 
          SecPadding.PKCS1SHA256, 
          digestBytes, 
          digest.count, 
          signatureBytes, 
          &signatureLength) 
     } 
    } 

    let count = signature.count - signatureLength 
    signature.removeLast(count) 

    guard result == noErr else { 
     throw MessageError(message: "Could not sign data: \(result)") 
    } 

    return signature.base64EncodedString() 
} 
関連する問題