Edw*_*oks 8 ruby cocoa licensing openssl rsa
我正在尝试为我的应用程序实现一个简单的许可证密钥方案,而且我遇到了很大的障碍.我在OpenSSL上关注许可证密钥的示例.
由于该博客文章是在2004年编写的,而OpenSSL已在OS X上弃用,我试图使用安全转换API来完成许可证密钥验证而不是OpenSSL.但是,我正在使用OpenSSL生成私钥和公钥; 许可证密钥是由Ruby Web应用程序使用私钥生成的,使用来自购买者电子邮件地址的SHA-256摘要的Ruby OpenSSL包装程序库.
问题是,我所做的任何事情似乎都不会使用OpenSSL从Ruby生成签名,而安全转换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))
Run Code Online (Sandbox Code Playgroud)
以及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);
Run Code Online (Sandbox Code Playgroud)
有谁知道我怎么能做这个工作?我已经花了好几天才到达我现在所处的位置,而且我已经筋疲力尽了我的调试能力,所以如果有任何人有任何见解,我将非常感激!
Kyr*_*kos 11
简而言之,你正在混淆一些关键概念.这是一个关于它如何工作的快速入门.
在红宝石方面,你会混淆签名和文件.您需要使用SHA256对许可证进行哈希处理,然后使用私钥对其进行加密以生成签名.您只是将文档的哈希值保存为签名.在红宝石方面试试这个:
require 'openssl'
require 'base64'
license = 'test@example.com'
private_key = OpenSSL::PKey::RSA.new(File.read('private_key.pem'))
digest = OpenSSL::Digest::SHA256.new
signature = private_key.sign digest, license
signature_out = Base64.encode64(signature)
File.write('signature.data', signature_out)
File.write('license_key.data', license) # no hash, no signing
Run Code Online (Sandbox Code Playgroud)
围绕这个的ruby文档可以在这里找到.
我不太熟悉你在Objective-C方面使用的库,但这里的技巧是确保你在两端使用相同的摘要算法进行散列(SHA256),检查相同的加密算法(RSA)和公钥和私钥兼容(匹配RSA模数和公共指数),以及来回传递的二进制签名数据的相同编码(base64,hex等)
在红宝石方面,你正在使用SHA256生成一个签名,而在objective-c上看起来你正在用SHA-2大小256进行验证,这样看起来还不错.
解码签名(如果你从ruby编写二进制文件,你可以跳过这个)
SecTransformRef decoder = SecDecodeTransformCreate(kSecBase64Encoding, &error);
if (error) { CFShow(error); exit(-1); }
SecTransformSetAttribute(decoder,
kSecTransformInputAttributeName,
signatureData,
&error);
if (error) { CFShow(error); exit(-1); }
CFDataRef signature = SecTransformExecute(decoder, &error);
if (error) { CFShow(error); exit(-1); }
Run Code Online (Sandbox Code Playgroud)
对于验证你想要这样的东西,从这里闪闪发光:
verifier = SecVerifyTransformCreate(publicKey, signature, &error);
if (error) { CFShow(error); exit(-1); } // show your errors!
SecTransformSetAttribute(verifier,
kSecTransformInputAttributeName,
cfLicense, // Converted from NSData
&error);
if (error) { CFShow(error); exit(-1); }
SecTransformSetAttribute(verifier,
kSecDigestTypeAttribute,
kSecDigestSHA2,
&error);
if (error) { CFShow(error); exit(-1); }
SecTransformSetAttribute(verifier,
kSecDigestLengthAttribute,
(__bridge CFNumberRef)@256,
&error);
if (error) { CFShow(error); exit(-1); }
result = SecTransformExecute(verifier, &error);
if (error) { CFShow(error); exit(-1); }
if (result == kCFBooleanTrue) {
/* Signature was valid. */
} else {
/* Signature was invalid. */
}
Run Code Online (Sandbox Code Playgroud)