iOS使用openSSL加密应该怎么做

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS使用openSSL加密应该怎么做相关的知识,希望对你有一定的参考价值。

最近几天折腾了一下如何在ios上使用RSA来加密。iOS上并没有直接的RSA加密API。但是iOS提供了x509的API,而x509是支持RSA加密的。因此,我们可以通过制作自签名的x509证书(由于对安全性要求不高,我们并不需要使用CA认证的证书),再调用x509的相关API来进行加密。接下来记录一下整个流程。
第一步,制作自签名的证书
1.最简单快捷的方法,打开Terminal,使用openssl(Mac OS X自带)生成私钥和自签名的x509证书。
openssl req -x509 -out public_key.der -outform der -new -newkey rsa:1024 -keyout private_key.pem -days 3650
按照命令行的提示输入内容就行了。
几个说明:
public_key.der是输出的自签名的x509证书,即我们要用的。
private_key.pem是输出的私钥,用来解密的,请妥善保管。
rsa:1024这里的1024是密钥长度,1024是比较安全的,如果需要更安全的话,可以用2048,但是加解密代价也会增加。
-days:证书过期时间,一定要加上这个参数,默认的证书过期时间是30天,一般我们不希望证书这么短就过期,所以写上比较合适的天数,例如这里的3650(10年)。
事实上,这一行命令包含了好几个步骤(我研究下面这些步骤的原因是我手头已经由一个private_key.pem私钥了,想直接用这个来生成x509证书,也就是用到了下面的2-3)
1)创建私钥
openssl genrsa -out private_key.pem 1024
2)创建证书请求(按照提示输入信息)
openssl req -new -out cert.csr -key private_key.pem
3)自签署根证书
openssl x509 -req -in cert.csr -out public_key.der -outform der -signkey private_key.pem -days 3650
2.验证证书。把public_key.der拖到xcode中,如果文件没有问题的话,那么就可以直接在xcode中打开,看到证书的各种信息。

第二步,使用public_key.der来进行加密。
1.导入Security.framework。
2.把public_key.der放到mainBundle中(一般直接拖到Xcode就行啦)。
3.从public_key.der读取公钥。
4.加密。
下面是参考代码(只能用于加密长度小于等于116字节的内容,适合于对密码进行加密。使用了ARC,不过还是要注意部分资源需要使用CFRealse来释放)
RSA.h
//
// RSA.h
//
#import Foundation.h>

@interface RSA : NSObject
SecKeyRef publicKey;
SecCertificateRef certificate;
SecPolicyRef policy;
SecTrustRef trust;
size_t maxPlainLen;


- (NSData *) encryptWithData:(NSData *)content;
- (NSData *) encryptWithString:(NSString *)content;

@end

RSA.m
//
// RSA.m
//
#import "RSA.h"

@implementation RSA

- (id)init
self = [super init];

NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key"
ofType:@"der"];
if (publicKeyPath == nil)
NSLog(@"Can not find pub.der");
return nil;


NSDate *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath];
if (publicKeyFileContent == nil)
NSLog(@"Can not read from pub.der");
return nil;


certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent);
if (certificate == nil)
NSLog(@"Can not read certificate from pub.der");
return nil;


policy = SecPolicyCreateBasicX509();
OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust);
if (returnCode != 0)
NSLog(@"SecTrustCreateWithCertificates fail. Error Code: %ld", returnCode);
return nil;


SecTrustResultType trustResultType;
returnCode = SecTrustEvaluate(trust, &trustResultType);
if (returnCode != 0)
NSLog(@"SecTrustEvaluate fail. Error Code: %ld", returnCode);
return nil;


publicKey = SecTrustCopyPublicKey(trust);
if (publicKey == nil)
NSLog(@"SecTrustCopyPublicKey fail");
return nil;


maxPlainLen = SecKeyGetBlockSize(publicKey) - 12;
return self;


- (NSData *) encryptWithData:(NSData *)content

size_t plainLen = [content length];
if (plainLen > maxPlainLen)
NSLog(@"content(%ld) is too long, must < %ld", plainLen, maxPlainLen);
return nil;


void *plain = malloc(plainLen);
[content getBytes:plain
length:plainLen];

size_t cipherLen = 128; // 当前RSA的密钥长度是128字节
void *cipher = malloc(cipherLen);

OSStatus returnCode = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plain,
plainLen, cipher, &cipherLen);

NSData *result = nil;
if (returnCode != 0)
NSLog(@"SecKeyEncrypt fail. Error Code: %ld", returnCode);

else
result = [NSData dataWithBytes:cipher
length:cipherLen];


free(plain);
free(cipher);

return result;


- (NSData *) encryptWithString:(NSString *)content
return [self encryptWithData:[content dataUsingEncoding:NSUTF8StringEncoding]];


- (void)dealloc
CFRelease(certificate);
CFRelease(trust);
CFRelease(policy);
CFRelease(publicKey);


@end

使用方法:
RSA *rsa = [[RSA alloc] init];
if (rsa != nil)
NSLog(@"%@",[rsa encryptWithString:@"test"]);

else
NSLog(@"init rsa error");
参考技术A 打开终端,进入项目根路径,执行这行命令就能执行了

使用openssl加密和解密一个小文件

【中文标题】使用openssl加密和解密一个小文件【英文标题】:Encrypting and decrypting a small file using openssl 【发布时间】:2010-11-03 16:30:27 【问题描述】:

我想用 C/C++ 编写一个小程序,它读取一个小文本文件,并使用“内部”密钥对其进行加密。然后我还想写另一个小程序,可以在内部使用相同的密钥解密加密文件。

我查看了 openSSL 网站并在 Google 上搜索,但发现不是简单的示例,有人尝试过这样做吗?

【问题讨论】:

一个类似例子的问题***.com/questions/3141860/… 你应该使用EVP_*函数。 EVP_* 函数使用硬件,如 AES-NI(如果可用)。请参阅 OpenSSL wiki 上的 EVP Symmetric Encryption and Decryption。事实上,您可能应该使用经过身份验证的加密,因为它提供 机密性和真实性。请参阅 OpenSSL wiki 上的 EVP Authenticated Encryption and Decryption。 【参考方案1】:

理想情况下,您可以使用现有的工具,例如 ccrypt,但这里是:

#include <openssl/aes.h>

/* ... */



  int bytes_read, bytes_written;
  unsigned char indata[AES_BLOCK_SIZE];
  unsigned char outdata[AES_BLOCK_SIZE];

  /* ckey and ivec are the two 128-bits keys necesary to
     en- and recrypt your data.  Note that ckey can be
     192 or 256 bits as well */
  unsigned char ckey[] =  "thiskeyisverybad";
  unsigned char ivec[] = "dontusethisinput";

  /* data structure that contains the key itself */
  AES_KEY key;

  /* set the encryption key */
  AES_set_encrypt_key(ckey, 128, &key);

  /* set where on the 128 bit encrypted block to begin encryption*/
  int num = 0;

  while (1) 
    bytes_read = fread(indata, 1, AES_BLOCK_SIZE, ifp);

    AES_cfb128_encrypt(indata, outdata, bytes_read, &key, ivec, &num,
           AES_ENCRYPT);

    bytes_written = fwrite(outdata, 1, bytes_read, ofp);
    if (bytes_read < AES_BLOCK_SIZE)
  break;
  

通过以AES_DECRYPT 作为最后一个参数调用AES_cfb128_encrypt 来完成解密。请注意,此代码只提供了最基本的测试,您确实应该为 ckey 和 ivec 使用适当的 8 位随机数据​​。

编辑:似乎AES_cfb128_encrypt 接受任意长度的数据,因此您不需要加密AES_BLOCK_SIZE (16) 字节的块。

【讨论】:

来自 aes 帮助文档的一些指导,说:并非所有可能的密钥大小和操作模式的变化都由这个库提供。由于这个原因和其他原因,应用程序应该使用更高级别的函数 L 等,而不是直接调用 AES 函数。 @Michiel Budding':我用过你的代码,需要初始化 int num;到 ivec 大小以使其正常工作。 ifp 和 ofp FILE 指针已被省略。它们应该在 while 循环之前用FILE *ifp = fopen("input_file", "rb"); FILE *ofp = fopen("output_file", "wb"); 声明【参考方案2】:

以前的答案已经为您指明了如何按照您的要求去做。

我想补充一下为什么你可能不应该这样做

您所说的称为“对称加密”(相同的密钥用于加密和解密,而不是非对称加密,使用一个密钥加密的所有内容只能由特定的对应方解密)。

反汇编可执行文件以确定正在使用的硬编码密钥几乎是微不足道的。这意味着,任何人只要掌握了您的一个可执行文件,就可以破解任何曾经交换过的消息的加密。

除非您心目中的应用程序非常具体,否则这意味着您的设置可能“看起来”安全,但实际上并非如此。在这些情况下,通常最好根本不加密,以免相关人员陷入这种虚假的安全感……

您正在寻找标准库来进行加密(而不是自己实现/创建算法),但是protocoll如何应用程序、密钥、和消息被使用和交换)至少与密码本身一样重要。您可能希望让从事密码学的人测试您的想法,以告诉您其中的弱点。 (我敢肯定 *** 上有足够的这种类型。;-))

【讨论】:

+1 的好建议。但是,与您所说的不同,至少有两个答案建议不要进行对称加密(Andrew Austin 和我的)。 我承认我没有通过链接了解它们的内容。 ;-) 我必须反对一点(当然我会);我们不知道 OP 的想法。如果加密和解密在不同的计算机上完成,内部密钥是安全的。如果他只是想玩弄 SSL 库,安全性是无关紧要的。我会给你 +1 的建议,但“你不应该这样做”的总结有点太强了。 现在是“可能”。我对 OP 有一种直觉,但你说得对,声明有点强。 @user93353:一切都很好,但是 OP 正在谈论一个“内部”密钥,它闻起来有“硬编码”的味道。【参考方案3】:

OpenSSL 特别关注实现 SSL 和 TLS,它们是通过网络加密数据的协议。由于您只是想加密文件,因此可以使用 OpenSSL,但并不理想。

相反,我会使用 BeeCrypt 或 Crypto++® Library 5.6.0 之类的东西,它们都提供了使用示例。

【讨论】:

OpenSSL 有内存和文件BIO,这是一个抽象。该库适用于内存缓冲区、文件缓冲区、套接字和其他 I/O 对象。库的加密部分 (libcrypto.a) 可以单独使用;并且 SSL 部分 (libssl.a) 建立在加密之上。

以上是关于iOS使用openSSL加密应该怎么做的主要内容,如果未能解决你的问题,请参考以下文章

加密技术---openss 理论

安全不安全001:openssl生成非对称加密RSA公钥密钥命令

openssl和CA

Linux OPENSSL的简单用法

OpenSSL 功能介绍

Linux里面openss-devel是啥?