【发布时间】:2015-04-27 05:08:28
【问题描述】:
我正在尝试为我的应用实施一个简单的许可证密钥方案,但遇到了重大障碍。我正在关注OpenSSL for License Keys 的示例。
自从那篇博文写于 2004 年并且 OpenSSL 在 OS X 上已被弃用以来,我正在尝试使用安全转换 API 来完成许可证密钥验证,而不是 OpenSSL。但是,我正在使用 OpenSSL 生成私钥和公钥;许可证密钥由 Ruby Web 应用使用 Ruby OpenSSL 包装库从购买者电子邮件地址的 SHA-256 摘要中的私钥生成。
问题是我所做的任何事情似乎都没有使用 OpenSSL 从 Ruby 生成签名,Security Transforms API 将验证该签名。
我正在处理的 Ruby 代码是:
require('openssl')
# The email address used as the content of the license key.
license = 'test@example.com'
# Generate the public/private keypair.
`openssl genrsa -out private_key.pem 2048`
`openssl rsa -in conductor.pem -out public_key.data -pubout`
# Get the private key and a hash of the license.
private_key = OpenSSL::PKey::RSA.new(File.read('private_key.pem'))
signature = OpenSSL::Digest::SHA256.digest(license)
# The signature passed to SecVerifyTransformCreate in the OS X app. I'm not sure which of these SecVerifyTransformCreate is expecting (the binary digest, a hex representation of the digest, or the original un-digested content), but none of them work.
signature_out = signature
#signature_out = OpenSSL::Digest::SHA256.hexdigest(license)
#signature_out = license
File.write('signature.data', signature_out)
# Sign the email address to generate the license key. Using the OpenSSL::PKey::PKey#sign method produces a license key that can only be verified on the command line by running:
#
# echo -n test@example.com | openssl dgst -sha256 -sign test.pem
#
# while using the #private_encrypt method produces a key that can only be verified on the command line by running:
#
# echo -n test@example.com | openssl dgst -sha256 -binary | openssl rsautl -sign -inkey test.pem
#
# I'm not sure what the exact difference between the two commands above is and why they correspond to the two different Ruby signing methods below. Neither approach produces something that SecVerifyTransformCreate will verify, however.
File.write('license_key.data',
private_key.sign(OpenSSL::Digest::SHA256.new, license))
# private_key.private_encrypt(signature))
以及Objective-C中对应的验证码:
// Get the data.
NSData *publicKeyData = [NSData dataWithContentsOfFile:@"public_key.data"];
NSData *signatureData = [NSData dataWithContentsOfFile:@"signature.data"];
NSData *licenseKeyData = [NSData dataWithContentsOfFile:@"license_key.data"];
// Import the public key.
SecItemImportExportKeyParameters keyParameters = {};
SecExternalFormat format = kSecFormatOpenSSL;
SecExternalItemType type = kSecItemTypePublicKey;
CFArrayRef publicKeys;
SecItemImport((__bridge CFDataRef)publicKeyData,
NULL,
&format,
&type,
0,
&keyParameters,
NULL,
&publicKeys);
NSArray *publicKeysArray = (__bridge_transfer NSArray *)publicKeys;
SecKeyRef publicKey = (__bridge SecKeyRef)publicKeysArray[0]; // TODO: How do we need to bridge this return value?
CFErrorRef error = NULL;
SecTransformRef verifier = SecVerifyTransformCreate(publicKey, (__bridge CFDataRef)signatureData, &error);
SecTransformSetAttribute(verifier, kSecTransformDebugAttributeName, kCFBooleanTrue, &error);
SecTransformSetAttribute(verifier, kSecTransformInputAttributeName, (__bridge CFDataRef)licenseKeyData, &error);
SecTransformSetAttribute(verifier, kSecDigestTypeAttribute, kSecDigestSHA2, &error);
SecTransformSetAttribute(verifier, kSecDigestLengthAttribute, (__bridge CFNumberRef)@256, &error);
// I'm not sure if one of these transform attributes is necessary, but neither of them produces a verified result anyways.
// SecTransformSetAttribute(verifier, kSecInputIsAttributeName, kSecInputIsDigest, &error);
// SecTransformSetAttribute(verifier, kSecInputIsAttributeName, kSecInputIsRaw, &error);
NSNumber *result = (__bridge NSNumber *)SecTransformExecute(verifier, &error);
NSLog(@"Result: %@", result);
有谁知道我怎样才能做到这一点?我确实花了几天时间才达到现在的水平,并且已经用尽了我的能力来进一步调试它,因此,如果有人有任何见解,将不胜感激!
【问题讨论】:
-
“自从那篇博文写于 2004 年并且 OpenSSL 在 OS X 上已被弃用,我正在尝试使用安全转换 API 来完成许可证密钥验证,而不是 OpenSSL。” - 另一种选择是在 OS X 上构建 OpenSSL 1.0.2 版本并使用它。有关在 OS X 上配置和构建的信息,请参阅 OpenSSL wiki 上的 Compilation and Installation。
-
感谢您的意见!如果我知道我现在所知道的并重新做一遍,我肯定会链接到 OpenSSL。但是,加密服务指南强烈建议您使用安全转换 API,我试图避免将另一个静态库链接到我的应用程序。在这一点上,由于我的代码大部分已经用 Security Transforms 编写了,我很想弄清楚缺少的部分是什么,而不是陷入切换到 OpenSSL 的兔子洞。
-
“但是,加密服务指南强烈建议您使用安全转换 API...” - 好吧,请考虑... Apple 并未修复所有安全问题错误,但 OpenSSL 有。例如,Apple 的某些版本的 Secure Transport 仍然存在ECDHE-ECDSA 错误。而CVE-2015-1130 (Hidden Backdoor with Root) 仅在最新操作系统的一个小版本中得到修复。据我所知,OpenSSL 修复了他们所有的错误(有时有很多错误)。
标签: ruby cocoa openssl licensing rsa