我的iOS应用程序,用swift编写,使用SecKeyCreateRandomKey为私钥(使用kSecAttrKeyTypeRSA和2048位属性)生成密钥对,使用SecKeyCopyPublicKey检索公钥。我使用SecKeyCreateSignature使用私钥对我的数据进行签名。
我将签名转换为字符串:signature?.base64EncodedString()
我使用SecKeyCopyExternalRepresentation将公钥SecKey结构转换为字符串,并将其转换为key.base64EncodedString()。
我将(使用HTTP POST和JSON)数据,公钥和签名发送到我的服务器。服务器将此信息存储在数据库中。
稍后,我的应用程序的其他一些实例会查询服务器,服务器会使用相关数据,签名和公钥进行响应。
在从服务器返回时,我使用SecKeyCreateWithData恢复公钥SecKey结构,然后应用程序使用签名和公钥使用SecKeyVerifySignature(使用.rsaSignatureMessagePKCS1v15SHA512算法)验证数据
这完美无瑕。签名,发送,存储...请求,检索,验证。因此,我知道,我来回传输数据没有问题,在应用程序方面没有让核心Apple安全功能工作的问题。但是:
我在验证PHP方面的签名时遇到了困难。理想情况下,我想在PHP服务器逻辑的各个点验证签名,数据,公钥。我尝试使用openssl_verify失败了。我试过(从数据库中读取):
$signature = base64_decode($row["signature"]);
$publicKey = $row["publicKey"];
$tA = $row["colA"];
$tB = $row["colB"];
$data = $tA . $tB;
$key = "-----BEGIN PUBLIC KEY----- " . $publicKey . " -----END PUBLIC KEY-----";
$ok = openssl_verify($data, $signature, $key, OPENSSL_ALGO_SHA512);
我不确定我做得对,我无法通过“强制”错误消息openssl_verify():提供的密钥参数不能被强制转换为公钥......
虽然文档声称_verify函数特别允许$ key也作为键的字符串传递,但是没有提供示例。所有的例子都处理文件和证书等。我把密钥加载到字符串中,我提供的“盔甲”iOS没有生成 - 我缺少什么?感谢帮助。
答案 0 :(得分:0)
我找到了一种解决方法(但仍在寻找openssl_verify解决方案)。 我找到了一个名为phpseclib的php库。我使用composer安装它(macos)并包含它:
require 'vendor/autoload.php';
use phpseclib\Crypt\RSA;
然后我将一个openssl_verify代码行替换为:
$rsa = new RSA();
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
$rsa->setHash('sha512');
$rsa->loadKey("-----BEGIN PUBLIC KEY-----\n" . trim($publicKey) . "\n-----END PUBLIC KEY-----");
$ok = $rsa->verify($data, $signature);
像魅力一样工作。如果有人告诉我如何使用openssl_verify这样做,我很乐意迁移。我看到有关这个图书馆的一些声音已经过时了。
答案 1 :(得分:0)
我遇到了同样的问题。我发现与其使用SecKeyCopyExternalRepresentation()
来导出公共密钥,是这样的:
CFDataRef publickeyBytes;
SecItemImportExportKeyParameters keyParams = { .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, .passphrase = @"" };
SecItemExport( publickey, kSecFormatOpenSSL, 0, &keyParams, &publickeyBytes );
为我提供了一种公钥,该公钥的格式可以仅使用openssl(在base64编码并添加-----BEGIN PUBLIC KEY-----
和-----END PUBLIC KEY-----
之后在PHP端导入)