一、突然发现少写了一个RSA - -#...,加解密原理参照RSA算法原理,常规的加解算法一般都是对称加密:
(1)甲方选择某一种加密规则,对信息进行加密
(2)乙方使用同一种规则,对信息进行解密。
由于加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法"(Symmetric-key algorithm)。
这种加密模式有一个最大弱点:甲方必须把加密规则告诉乙方,否则无法解密。保存和传递密钥,就成了最头疼的问题。
常用的是AES如:iOS开发加解密算法-基础篇(2)<AES加密算法>
而RSA是非对称加密:
(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
(2)甲方获取乙方的公钥,然后用它对信息加密。
(3)乙方得到加密后的信息,用私钥解密。
如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。
特点
A.便于理解,使用广泛
RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。
B.缺点与不足:加密和解密花费时间长、速度慢,只适合对少量数据进行加密。
为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。
二、RSA的方法实现:
1.一般移动端的RSA加解密的公私钥都是由服务端生成的,我们要做的其实是拿着公私钥去做加解密的操作。
2.我们公司的项目使用的加解密流程是
虽然RSA加密后基本无解,但是RSA不适合对大文本进行加密,所以我们采用的是对文件采用AES加密,对AES的秘钥进行RSA的加密,AES秘钥是动态的每一个文件的秘钥都是唯一的,RSA的私钥在传输的时候再用一层AES加密.解密的流程就是再倒着来一遍...
3.RSA解密,使用第三方加解密库openssl
- 一般公私钥都是由我们服务端提供的的(java后台),这里遇到过坑,我们当时双方都没做过RSA的加解密,格子调研在自己的平台上自己加密和解密是没有问题的,但是用服务端传给我们的私钥解密他们的加密文本却不能解密。最后发现原来生成的跨平台的私钥不能直接使用,需要进行统一的编码处理后才能使用,我们采用的是统一的PKCS#8编码处理后生成的.pem格式。可以参考:Java中使用OpenSSL生成的RSA公私钥进行数据加解密
2.秘钥文本
AES秘钥经过RSA加密后的Base64字符串<code>
key = eY4bZZsiqDCsNgHVaT5OJfDkGp5pNlJbYUUPOTauXO5Yz9szXgz1XOmjTq8aoPnHTkuh1GCSF/hj0g182U2iUTZFIwRoL7MZ/LtuTpwDMaa3XHAOjvTqxfHKy3htd9gpR/2/w9+l9urm2MPS31GD/ZalX8GGBltDVNZWXj0zyX4=;</code>
RSA私钥经过PKCS#8编码处理后获取的私钥字符串:
<code>
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCWWQqoCxHmu9yklZ7DAME9lvw0t37SqBhIcvnma7Rl3kTn4lfJ
WEoycvNmduhf59g193c8/4tQKs/B71OUIDWfASNhnaBVzyHXTupeUSo5yaXYdSja
VIhc/HmSms1SqlsDWBzJldi0JVaN5MqNnitHpxPOBHEu6J3Xr+Cobkd1XwIDAQAB
AoGAVHmtQiQOJ92QKK2kqZ6H9SobhSdAy+4EzthDT1Ne5gnQH5YOiyPfdJ8f4YeY
IyLqWdA0oAJZbW7Qkv/8rvK2DUbH97LkeGOuJtY5SxmbWI0w7fGvefg9TPrDSyRq
PWvohEZSM2w7slhHTiPFeiRFIEmuWGTJAcnmPLAraxn5QTkCQQDWfX4ybSk5mX9y
iSt952C78c80bX54XW9VMCnDIFGDkSsG3zyXlI4i3PJAXYHFwzcysD0irxQPVjTA
7k6b1eflAkEAs3G8mxCAbuqbzw7zuJUgMshns2tD5BIH8/7DwhRl/ecz6Az6SQ6Q
ZF02XpDyqpNtllwc2WDIyTE7go33bNeL8wJBALYb6Hix/A1+iRna4sVMHPKV1QJD
cNyLIAqpENwt5Weaani0MwLTy3ZIN5p0ick5/PSZc96t3Y9D9xhTfQSMsg0CQFlC
wmcAFmMWINsmvOWciJ+6QJtnSCYzMfGVURtBulpKn+9WRUoCDKFgHKN9xrhDDcg1
mcQn+Ljb3JZcuC9UKTECQQCRCHnaY7sp3hIizdIRN5lI0vhyipVVIymTTgmtu7rV
LrnmEEas1RhUVOyVJaw08mON/eH17//9X29cA9ntFSLh
-----END RSA PRIVATE KEY-----
</code>
4.代码实现
a.将私钥写入到本地后缀名不限制
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@".private_key.rce"];
NSFileManager *manger = [NSFileManager defaultManager];
[manger removeItemAtPath:path error:nil];
NSError *error = nil;
BOOL success = [str writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error];
b.将私钥导入
//根据钥匙类型导入公钥私钥
- (BOOL)importRSAKeyWithType:(KeyType)type {
FILE *file;
if (type == KeyTypePublic) {
file = fopen([OpenSSLRSAPublicKeyFile cStringUsingEncoding:NSASCIIStringEncoding],"rb");
}else{
file = fopen([OpenSSLRSAPrivateKeyFile1 cStringUsingEncoding:NSASCIIStringEncoding],"rb");
}
if (NULL != file) {
if (type == KeyTypePublic) {
_rsa = PEM_read_RSAPublicKey(file,NULL, NULL, NULL);
assert(_rsa != NULL);
// PEM_write_RSAPublicKey(stdout, _rsa);
}else{
_rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);
assert(_rsa != NULL);
PEM_write_RSAPrivateKey(stdout, _rsa, NULL, NULL, 0, NULL, NULL);
}
fclose(file);
return (_rsa != NULL)?YES:NO;
} return NO;
}
c.导入完成后对加密二进制流进行解密
- (NSData*)decryptRSAKeyWithType:(KeyType)keyType paddingType:(RSA_PADDING_TYPE)padding encryptedData:(NSData*)data {
if (data && [data length]) {
NSUInteger flen = [data length];
unsigned char from[flen];
bzero(from, sizeof(from));
memcpy(from, [data bytes], [data length]);
// 这里可以更改解密密文长度
unsigned char to[32];
bzero(to, sizeof(to));
[self decryptRSAKeyWithType:keyType :from :flen :to :padding];
NSData *data = [NSData dataWithBytes:to length:sizeof(to)];
[[NSFileManager defaultManager] removeItemAtPath:OpenSSLRSAPrivateKeyFile1 error:nil];
return data;
}
return nil;
}
- (NSData *)decryptRSAKeyWithType:(KeyType)keyType paddingType:(RSA_PADDING_TYPE)padding encryptedData:(NSData *)data andKeyName:(NSString *)name {
[self importRSAKeyWithType:KeyTypePrivate keyName:name];
if (data && [data length])
{
NSUInteger flen = [data length];
unsigned char from[flen];
bzero(from, sizeof(from));
memcpy(from, [data bytes], [data length]);
unsigned char to[32];
bzero(to, sizeof(to));
[self decryptRSAKeyWithType:keyType :from :flen :to :padding];
return [NSData dataWithBytes:to length:sizeof(to)];
}
return nil;
}