如何在iOS下使用加密密钥对字符串进行签名?
我有用 Java 创建的密钥。私钥采用 PKCS#8 加密,采用 PEM 字符串形式。
以下是在 Python 中将私钥与 M2Crypto 结合使用的示例:
from M2Crypto import EVP, BIO
privpem = "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIICoTAbBgoqhkiG9w0BDAEDMA0ECFavEvdkv3fEAgEUBIICgAWvHvH6OktLiaaqo9v+X6XEuY3M\nZr465VmZWzP9nsbTqwSKQQjseiD/rWAxK7RS+V+hit5ZxlNRAUbkg0kwl8SRNX3v6q8noJtcB0OY\ndBEuNJDmWHMHh8qcnfRYc9WXPPmWdjQM2AkfZNfNOxHVlOMhancScy6P4h3Flri9VyUE8w2/zZqK\nBAd2w39V7gprCQXnnNenNuvr4p8MjsdBm8jh00o2HJzN0I6u+9s7M3qLXxwxNepptgU6Qt6eKHi6\njpsV/musVaohLhFMFAzQ87FeGvz/W8dyS9BtAKMRSuDu/QdWIJMRNKkPT0Tt1243V3tzXVXLjz0u\nm/FX6kfxL8r+eGtTr6NKTG75TJfooQzN/v08OEbmvYD/mfptmZ7uKezOGxDmgynn1Au7T/OxKFhx\nWZHpb9OFPIU0uiriUeyY9sbDVJ054zQ/Zd5+iaIjX5RsLoB4J+pfr4HuiVIZVj+Ss2rnPsOY3SjM\ntbHIFp/fLr/HODcDA5eYADRGpBIL9//Ejgzd7OqpU0mdajzZHcMTjeXfWB0cc769bFyHb3Ju1zNO\ng4gNN1H1kOMAXMF7p6r25f6v1BRS6bQyyiFz7Hs7h7JBylbBAgQJgZvv9Ea3XTMy+DIPMdepqu9M\nXazmmYJCtdLAfLBybWsfSBU5K6Pm6+Bwt6mPsuvYQBrP3h84BDRlbkntxUgaWmTB4dkmzhMS3gsY\nWmHGb1N+rn7xLoA70a3U/dUlI7lPkWBx9Sz7n8JlH3cM6jJUmUbmbAgHiyQkZ2mf6qo9qlnhOLvl\nFiG6AY+wpu4mzM6a4BiGMNG9D5rnNyD16K+p41LsliI/M5C36PKeMQbwjJKjmlmWDX0=\n-----END ENCRYPTED PRIVATE KEY-----\n"
msg = "This is a message."
privkeybio = BIO.MemoryBuffer(privpem)
privkey = EVP.load_key_bio(privkeybio) #pw: 123456
privkey.sign_init()
privkey.sign_update(msg)
print privkey.sign_final().encode('base64')
以下是如何在 Java 中使用 PEM(剥离页眉和页脚)的示例:
String msg = "This is a message.";
String privpem = "MIICoTAbBgoqhkiG9w0BDAEDMA0ECFavEvdkv3fEAgEUBIICgAWvHvH6OktLiaaqo9v+X6XEuY3M\nZr465VmZWzP9nsbTqwSKQQjseiD/rWAxK7RS+V+hit5ZxlNRAUbkg0kwl8SRNX3v6q8noJtcB0OY\ndBEuNJDmWHMHh8qcnfRYc9WXPPmWdjQM2AkfZNfNOxHVlOMhancScy6P4h3Flri9VyUE8w2/zZqK\nBAd2w39V7gprCQXnnNenNuvr4p8MjsdBm8jh00o2HJzN0I6u+9s7M3qLXxwxNepptgU6Qt6eKHi6\njpsV/musVaohLhFMFAzQ87FeGvz/W8dyS9BtAKMRSuDu/QdWIJMRNKkPT0Tt1243V3tzXVXLjz0u\nm/FX6kfxL8r+eGtTr6NKTG75TJfooQzN/v08OEbmvYD/mfptmZ7uKezOGxDmgynn1Au7T/OxKFhx\nWZHpb9OFPIU0uiriUeyY9sbDVJ054zQ/Zd5+iaIjX5RsLoB4J+pfr4HuiVIZVj+Ss2rnPsOY3SjM\ntbHIFp/fLr/HODcDA5eYADRGpBIL9//Ejgzd7OqpU0mdajzZHcMTjeXfWB0cc769bFyHb3Ju1zNO\ng4gNN1H1kOMAXMF7p6r25f6v1BRS6bQyyiFz7Hs7h7JBylbBAgQJgZvv9Ea3XTMy+DIPMdepqu9M\nXazmmYJCtdLAfLBybWsfSBU5K6Pm6+Bwt6mPsuvYQBrP3h84BDRlbkntxUgaWmTB4dkmzhMS3gsY\nWmHGb1N+rn7xLoA70a3U/dUlI7lPkWBx9Sz7n8JlH3cM6jJUmUbmbAgHiyQkZ2mf6qo9qlnhOLvl\nFiG6AY+wpu4mzM6a4BiGMNG9D5rnNyD16K+p41LsliI/M5C36PKeMQbwjJKjmlmWDX0=";
byte [] privkeybytes = Base64.decode(privpem);
EncryptedPrivateKeyInfo encprivki = new EncryptedPrivateKeyInfo(privkeybytes);
Cipher cipher = Cipher.getInstance(encprivki.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec("123456".toCharArray());
SecretKeyFactory secFac = SecretKeyFactory.getInstance(encprivki.getAlgName());
Key pbeKey = secFac.generateSecret(pbeKeySpec);
AlgorithmParameters algParams = encprivki.getAlgParameters();
cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
KeySpec pkcs8KeySpec = encprivki.getKeySpec(cipher);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey pk = kf.generatePrivate(pkcs8KeySpec);
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign(pk);
sig.update(msg.getBytes("UTF8"));
byte[] signatureBytes = sig.sign();
String b = Base64.encodeBytes(signatureBytes, Base64.DO_BREAK_LINES);
System.out.println(b); // Display the string.
在 iOS 中这将如何完成?我已经查看了 CryptoExercise,特别是 SecKeyWrapper,但是那里发生了很多事情,而且超出了我的范围。
我个人不会进行 iOS 开发,但我需要一些代码来提供给开发人员,以至少或多或少地展示如何做到这一点。开发者更多的是 UI 类型,不熟悉加密。 (我也不是,但这是一个不同的故事......)
当我们这样做时,如何根据字符串公钥 PEM 验证签名?我不会在这里放置 Java 和 Python 示例,因为它们非常简单。
I have keys created in Java. The private key is PKCS#8 encrypted, in PEM string.
Here is an example of using the private key with M2Crypto in Python:
from M2Crypto import EVP, BIO
privpem = "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIICoTAbBgoqhkiG9w0BDAEDMA0ECFavEvdkv3fEAgEUBIICgAWvHvH6OktLiaaqo9v+X6XEuY3M\nZr465VmZWzP9nsbTqwSKQQjseiD/rWAxK7RS+V+hit5ZxlNRAUbkg0kwl8SRNX3v6q8noJtcB0OY\ndBEuNJDmWHMHh8qcnfRYc9WXPPmWdjQM2AkfZNfNOxHVlOMhancScy6P4h3Flri9VyUE8w2/zZqK\nBAd2w39V7gprCQXnnNenNuvr4p8MjsdBm8jh00o2HJzN0I6u+9s7M3qLXxwxNepptgU6Qt6eKHi6\njpsV/musVaohLhFMFAzQ87FeGvz/W8dyS9BtAKMRSuDu/QdWIJMRNKkPT0Tt1243V3tzXVXLjz0u\nm/FX6kfxL8r+eGtTr6NKTG75TJfooQzN/v08OEbmvYD/mfptmZ7uKezOGxDmgynn1Au7T/OxKFhx\nWZHpb9OFPIU0uiriUeyY9sbDVJ054zQ/Zd5+iaIjX5RsLoB4J+pfr4HuiVIZVj+Ss2rnPsOY3SjM\ntbHIFp/fLr/HODcDA5eYADRGpBIL9//Ejgzd7OqpU0mdajzZHcMTjeXfWB0cc769bFyHb3Ju1zNO\ng4gNN1H1kOMAXMF7p6r25f6v1BRS6bQyyiFz7Hs7h7JBylbBAgQJgZvv9Ea3XTMy+DIPMdepqu9M\nXazmmYJCtdLAfLBybWsfSBU5K6Pm6+Bwt6mPsuvYQBrP3h84BDRlbkntxUgaWmTB4dkmzhMS3gsY\nWmHGb1N+rn7xLoA70a3U/dUlI7lPkWBx9Sz7n8JlH3cM6jJUmUbmbAgHiyQkZ2mf6qo9qlnhOLvl\nFiG6AY+wpu4mzM6a4BiGMNG9D5rnNyD16K+p41LsliI/M5C36PKeMQbwjJKjmlmWDX0=\n-----END ENCRYPTED PRIVATE KEY-----\n"
msg = "This is a message."
privkeybio = BIO.MemoryBuffer(privpem)
privkey = EVP.load_key_bio(privkeybio) #pw: 123456
privkey.sign_init()
privkey.sign_update(msg)
print privkey.sign_final().encode('base64')
And here is example of how I can use the PEM (with header and footer stripped off) in Java:
String msg = "This is a message.";
String privpem = "MIICoTAbBgoqhkiG9w0BDAEDMA0ECFavEvdkv3fEAgEUBIICgAWvHvH6OktLiaaqo9v+X6XEuY3M\nZr465VmZWzP9nsbTqwSKQQjseiD/rWAxK7RS+V+hit5ZxlNRAUbkg0kwl8SRNX3v6q8noJtcB0OY\ndBEuNJDmWHMHh8qcnfRYc9WXPPmWdjQM2AkfZNfNOxHVlOMhancScy6P4h3Flri9VyUE8w2/zZqK\nBAd2w39V7gprCQXnnNenNuvr4p8MjsdBm8jh00o2HJzN0I6u+9s7M3qLXxwxNepptgU6Qt6eKHi6\njpsV/musVaohLhFMFAzQ87FeGvz/W8dyS9BtAKMRSuDu/QdWIJMRNKkPT0Tt1243V3tzXVXLjz0u\nm/FX6kfxL8r+eGtTr6NKTG75TJfooQzN/v08OEbmvYD/mfptmZ7uKezOGxDmgynn1Au7T/OxKFhx\nWZHpb9OFPIU0uiriUeyY9sbDVJ054zQ/Zd5+iaIjX5RsLoB4J+pfr4HuiVIZVj+Ss2rnPsOY3SjM\ntbHIFp/fLr/HODcDA5eYADRGpBIL9//Ejgzd7OqpU0mdajzZHcMTjeXfWB0cc769bFyHb3Ju1zNO\ng4gNN1H1kOMAXMF7p6r25f6v1BRS6bQyyiFz7Hs7h7JBylbBAgQJgZvv9Ea3XTMy+DIPMdepqu9M\nXazmmYJCtdLAfLBybWsfSBU5K6Pm6+Bwt6mPsuvYQBrP3h84BDRlbkntxUgaWmTB4dkmzhMS3gsY\nWmHGb1N+rn7xLoA70a3U/dUlI7lPkWBx9Sz7n8JlH3cM6jJUmUbmbAgHiyQkZ2mf6qo9qlnhOLvl\nFiG6AY+wpu4mzM6a4BiGMNG9D5rnNyD16K+p41LsliI/M5C36PKeMQbwjJKjmlmWDX0=";
byte [] privkeybytes = Base64.decode(privpem);
EncryptedPrivateKeyInfo encprivki = new EncryptedPrivateKeyInfo(privkeybytes);
Cipher cipher = Cipher.getInstance(encprivki.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec("123456".toCharArray());
SecretKeyFactory secFac = SecretKeyFactory.getInstance(encprivki.getAlgName());
Key pbeKey = secFac.generateSecret(pbeKeySpec);
AlgorithmParameters algParams = encprivki.getAlgParameters();
cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
KeySpec pkcs8KeySpec = encprivki.getKeySpec(cipher);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey pk = kf.generatePrivate(pkcs8KeySpec);
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign(pk);
sig.update(msg.getBytes("UTF8"));
byte[] signatureBytes = sig.sign();
String b = Base64.encodeBytes(signatureBytes, Base64.DO_BREAK_LINES);
System.out.println(b); // Display the string.
How would this be done in iOS? I have looked at the CryptoExercise, in particular the SecKeyWrapper, but there is lots going on there, and it's beyond me.
I am not personally going to be doing the iOS development, but I need some code to give to the developer to at least show more or less how to do it. The developer is more a UI type and not familiar with crypto. (Neither am I but that is a different story...)
And while we're at it, how to verify a signature against a string public key PEM? I won't put the Java and Python examples here as they are pretty straight forward.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
上周我也遇到了同样的问题。 iOS 上的 CommonCrypt 库非常适合对称密钥加密,但处理密钥环来完成简单的公钥操作太麻烦了。在花了大约半个小时研究之后,我刚刚添加了 OpenSSL。 OpenSSL-Xcode 使设置变得很简单 - 只需将项目和 OpenSSL tarball 放入,设置您的目标是与 libssl 链接,然后就可以开始了。
OpenSSL 代码看起来与 M2Crypto 代码几乎相同。
I had the same problem last week. The CommonCrypt library on iOS is very nice for symmetric key encryption, but it's just too much hassle dealing with the keyring to do simple public key things. After spending about half an hour poking at it I just included OpenSSL. OpenSSL-Xcode made this trivial to set up - just drop the project and the OpenSSL tarball in, set your target to link with libssl, and you're good to go.
The OpenSSL code looks nearly the same as the M2Crypto one.