object-c 使用openssl进行 rsa 双向加解密

 

IOS系统本身自带的RSA加密类有个特性,那就是加解密是单向的,就是只能 公钥加密->私钥解密,反之则会报错。

 

所以很多朋友就会出现这样的情况,在IOS客户端用公钥加密的数据传到服务器端用私钥解密没有问题。但反过来在服务器端用私钥加密的数据传到IOS客户端用公钥解密,就报-9809或-50的错误。你的服务器端可能是JAVA或者其他语言写的。

 

很多朋友网上找不到解决案例。我开始也遇到这样的问题,最后果断用了下openssl,使用openssl库才解决了这个问题。使用openssl既可以使用公钥加密,也可以使用私钥进行加密,而且与服务器端的加解密的结果相同。下面我们就一起来捣鼓一下吧。

在IOS上要使用openssl需要先编译openssl的库才能使用,我这里已经编译好了直接下载就可以使用,http://download.csdn.net/detail/kokjuis/9723109 点击打开链接

 

至于OpenSSL怎么生成公私钥,这个不写了,网上一大把。

 

下载完以后解压,然后导入到你的xcode工程中,不一定跟我的路径一样,自己根据情况改成自己的路径

 

然后在build settings的Header Search Paths里面引用 include路径,并且把Always Search User Paths设置为Yes,如图:

 

 

 

然后在 Library Search Paths 引用lib目录。一般导入以后XCODE会自动引用的,如果没有引用,自己手动引用一下。

 

 

到这里就基本能正常使用openssl库的加解密功能了,下面是我写的一个工具类,可以参考一下,是用OC语言写的,想用Swift写的话也很简单,可以自己转换一下,这里不折腾了:

 

 

 

//
//  IOS使用OpenSSL 生成的公私玥字符串进行RSA加解密
//  RsaUtil.h
//
//  Created by kokjuis on 16/8/19.
//
//

#import <Foundation/Foundation.h>
#import <openssl/rsa.h>
#import <openssl/pem.h>

@interface RsaUtil : NSObject


/*
 注意,RSA加解密的特征是:公钥加密->私钥解密、私钥加密->公钥解密。
 */

+(NSString *) encryptString:(NSString *)content withPublicKey:(NSString *)publicKey;//公钥加密
+(NSString *) decryptString:(NSString *)encryptContent withPublicKey:(NSString *)publicKey;//公钥解密

+(NSString *) encryptString:(NSString *)content withPrivateKey:(NSString *)privateKey;//私钥加密
+(NSString *) decryptString:(NSString *)encryptContent withPrivateKey:(NSString *)privateKey;//私钥解密

@end

 

 

 

 

//
//  RsaUtil.m
//  BestTravel
//
//  Created by kokjuis on 16/8/19.
//
//

#import "RsaUtil.h"
#import <Security/Security.h>
//#import "GTMBase64.h"

@implementation RsaUtil


#pragma mark -通过公私钥字符串生成公私钥
//通过公钥生成key
+(RSA *)createRsaKeyWithPublicKey:(NSString *) publicKey{
    
    
    //为了避免写法的不同意,如果公钥已经带有下面标记字符,先去除,后面再统一加上固定格式
    NSRange spos = [publicKey rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
    NSRange epos = [publicKey rangeOfString:@"-----END PUBLIC KEY-----"];
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        publicKey = [publicKey substringWithRange:range];
    }
    
    //除去换行符,空格等
    publicKey = [publicKey stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    publicKey = [publicKey stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    publicKey = [publicKey stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    publicKey = [publicKey stringByReplacingOccurrencesOfString:@" "  withString:@""];
    
    // ras公钥
    NSMutableString * rsa_public_key = [[NSMutableString alloc]initWithString:publicKey];
    
    //从内存中读取,公钥字符串开头要加上“-----BEGIN PUBLIC KEY-----\n”,结尾加上“\n-----END PUBLIC KEY-----\n”。否则会出现error:0906D06C:PEM routines:PEM_read_bio:no start line
    [rsa_public_key insertString:@"-----BEGIN PUBLIC KEY-----\n" atIndex:0];
    [rsa_public_key appendString:@"\n-----END PUBLIC KEY-----\n"];
    
    BIO *bio = NULL;
    const char * chPublicKey =[rsa_public_key UTF8String];
    if ((bio = BIO_new_mem_buf(chPublicKey, -1)) == NULL)       //从字符串读取RSA公钥
    {
        return nil;
    }
    
    RSA *rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);   //从bio结构中得到rsa结构
    
    return rsa;
    
}

//通过私钥生成key
+(RSA *)createRsaKeyWithPrivateKey:(NSString *) privateKey{
    
    
    //为了避免写法的不同意,如果私钥已经带有下面标记字符,先去除,后面再统一加上固定格式
    NSRange spos = [privateKey rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
    NSRange epos = [privateKey rangeOfString:@"-----END RSA PRIVATE KEY-----"];
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        privateKey = [privateKey substringWithRange:range];
    }
    
    //除去换行符,空格等
    privateKey = [privateKey stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    privateKey = [privateKey stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    privateKey = [privateKey stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    privateKey = [privateKey stringByReplacingOccurrencesOfString:@" "  withString:@""];

    
    // ras私钥
    NSMutableString * rsa_private_key = [[NSMutableString alloc]initWithString:privateKey];
    
    //从内存中读取,公钥字符串开头要加上“-----BEGIN RSA PRIVATE KEY-----\n”,结尾加上“\n-----END RSA PRIVATE KEY-----\n”。否则会出现error:0906D06C:PEM routines:PEM_read_bio:no start line
    [rsa_private_key insertString:@"-----BEGIN RSA PRIVATE KEY-----\n" atIndex:0];
    [rsa_private_key appendString:@"\n-----END RSA PRIVATE KEY-----\n"];
    
    
    BIO *bio = NULL;
    const char * chPrivateKey =[rsa_private_key UTF8String];
    if ((bio = BIO_new_mem_buf(chPrivateKey, -1)) == NULL)       //从字符串读取RSA公钥
    {
        return nil;
    }

    RSA *rsa=PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
    
    return rsa;
    
}




#pragma mark -公钥加解密
//分段加密
+ (NSData *) encryptData:(NSData *)data withPublicRSA:(RSA *)publicRSA{
    
    //获取公钥
    if (!publicRSA) {
        return nil;
    }
    
    int publicRSALength = RSA_size(publicRSA);          //公钥长度
    double totalLength = [data length];                 //数据总长度
    int blockSize = publicRSALength - 12;                //数据分段大小
    int blockCount = ceil(totalLength / blockSize);     //分段个数
    size_t publicEncryptSize = publicRSALength;
    NSMutableData *encryptDate = [NSMutableData data];
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        int dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        NSData *dataSegment = [data subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        char *publicEncrypt = malloc(publicRSALength);
        memset(publicEncrypt, 0, publicRSALength);
        const unsigned char *str = [dataSegment bytes];
        if(RSA_public_encrypt(blockSize,str,(unsigned char*)publicEncrypt,publicRSA,RSA_PKCS1_PADDING)>=0){
            NSData *encryptData = [[NSData alloc] initWithBytes:publicEncrypt length:publicEncryptSize];
            [encryptDate appendData:encryptData];
        }
        free(publicEncrypt);
    }
    RSA_free(publicRSA);
    
    return encryptDate;
}



//分段解密
+ (NSData *) decryptData:(NSData *)data withPublicRSA:(RSA *)publicRSA{
    
    if (!publicRSA) {
        return nil;
    }
   
    int publicRSALength = RSA_size(publicRSA);
    double totalLength = [data length];
    int blockSize = publicRSALength;
    int blockCount = ceil(totalLength / blockSize);
    NSMutableData *decrypeData = [NSMutableData data];
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        long dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        NSData *dataSegment = [data subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        const unsigned char *str = [dataSegment bytes];
        unsigned char *privateDecrypt = malloc(publicRSALength);
        memset(privateDecrypt, 0, publicRSALength);
        if(RSA_public_decrypt(publicRSALength,str,privateDecrypt,publicRSA,RSA_PKCS1_PADDING)>=0){
            NSInteger length =strlen((char *)privateDecrypt);
            NSData *data = [[NSData alloc] initWithBytes:privateDecrypt length:length];
            [decrypeData appendData:data];
        }
        free(privateDecrypt);
    }
    
    RSA_free(publicRSA);
    
    return decrypeData;
}



#pragma 加密
+ (NSString *) encryptString:(NSString *)content withPublicKey:(NSString *)publicKey{
    //加密
    
    RSA *publicRSA=[self createRsaKeyWithPublicKey:publicKey];
    
    NSData *data=[self encryptData:[content dataUsingEncoding:NSUTF8StringEncoding] withPublicRSA:publicRSA];
    
    //NSData *encodeData=[GTMBase64 encodeData:data];
    NSData * encodeData = [data base64EncodedDataWithOptions:0];
    
    NSString * encrypotoResult= [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding];
    
    return encrypotoResult;
}

#pragma 解密
+(NSString *) decryptString:(NSString *)encryptContent withPublicKey:(NSString *)publicKey{
    //解密
    
     RSA *publicRSA=[self createRsaKeyWithPublicKey:publicKey];
    
    //NSData *encodeData=[GTMBase64 decodeString:encryptContent];
     NSData *encodeData = [[NSData alloc] initWithBase64EncodedString:encryptContent options:NSDataBase64DecodingIgnoreUnknownCharacters];
    
    NSData *data=[self decryptData:encodeData withPublicRSA:publicRSA];
    NSString * decrypotoResult= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    return decrypotoResult;
}



#pragma mark -私钥加解密

//私钥加密
+ (NSData *)encryptDate:(NSData *)data withPrivateRSA:(RSA *)privateRSA{
    
    if (!privateRSA) {
        return nil;
    }
    int privateRSALength = RSA_size(privateRSA);          //公钥长度
    double totalLength = [data length];                 //数据总长度
    int blockSize = privateRSALength - 12;                //数据分段大小
    int blockCount = ceil(totalLength / blockSize);     //分段个数
    size_t privateEncryptSize = privateRSALength;
    NSMutableData *encryptDate = [NSMutableData data];
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        int dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        NSData *dataSegment = [data subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        char *publicEncrypt = malloc(privateRSALength);
        memset(publicEncrypt, 0, privateRSALength);
        const unsigned char *str = [dataSegment bytes];
        if(RSA_private_encrypt(dataSegmentRealSize,str,(unsigned char*)publicEncrypt,privateRSA,RSA_PKCS1_PADDING)>=0){
            NSData *encryptData = [[NSData alloc] initWithBytes:publicEncrypt length:privateEncryptSize];
            [encryptDate appendData:encryptData];
        }
        free(publicEncrypt);
    }
    RSA_free(privateRSA);
    return encryptDate;
}

//私钥解密
+ (NSData *)decryptData:(NSData *)data withPrivateRSA:(RSA *)privateRSA {
    
    if (!privateRSA) {
        return nil;
    }
    
    int privateRSALenght = RSA_size(privateRSA);
    double totalLength = [data length];
    int blockSize = privateRSALenght;
    int blockCount = ceil(totalLength / blockSize);
    NSMutableData *decrypeData = [NSMutableData data];
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        long dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        NSData *dataSegment = [data subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        const unsigned char *str = [dataSegment bytes];
        unsigned char *privateDecrypt = malloc(privateRSALenght);
        memset(privateDecrypt, 0, privateRSALenght);
        if(RSA_private_decrypt(privateRSALenght,str,privateDecrypt,privateRSA,RSA_PKCS1_PADDING)>=0){
            NSInteger length =strlen((char *)privateDecrypt);
            NSData *data = [[NSData alloc] initWithBytes:privateDecrypt length:length];
            [decrypeData appendData:data];
            
        }
        free(privateDecrypt);
    }
    
    RSA_free(privateRSA);
    return decrypeData;
}



#pragma 加密
+ (NSString *) encryptString:(NSString *)content withPrivateKey:(NSString *)privateKey{
    //加密
    
    RSA *privateRSA=[self createRsaKeyWithPrivateKey:privateKey];
    
    NSData *data=[self encryptDate:[content dataUsingEncoding:NSUTF8StringEncoding] withPrivateRSA:privateRSA];
   // NSData *encodeData=[GTMBase64 encodeData:data];
    NSData * encodeData = [data base64EncodedDataWithOptions:0];
    NSString * encrypotoResult= [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding];
    
    return encrypotoResult;
}


#pragma 解密
+(NSString *) decryptString:(NSString *)encryptContent withPrivateKey:(NSString *)privateKey{
    //解密
    
      RSA *privateRSA=[self createRsaKeyWithPrivateKey:privateKey];
    
    //可以用系统自带的base64,也可以用GTMBase64这个库
    //NSData *encodeData=[GTMBase64 decodeString:encryptContent];
    NSData *encodeData = [[NSData alloc] initWithBase64EncodedString:encryptContent options:NSDataBase64DecodingIgnoreUnknownCharacters];
    
    NSData *data=[self decryptData:encodeData withPrivateRSA:privateRSA];
    NSString * decrypotoResult= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    return decrypotoResult;
}



@end

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用C语言和OpenSSL编写RSA加密解密算法的代码及注释: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/bio.h> #include <openssl/evp.h> #include <openssl/rsa.h> #define KEY_LENGTH 2048 // RSA密钥长度 #define PUB_EXP 3 // RSA公钥指数 // RSA密钥对结构体 typedef struct _rsa_keys { RSA *public_key; RSA *private_key; } rsa_keys; // 生成RSA密钥对函数 int generate_rsa_keys(rsa_keys *keys) { int ret = 0; BIGNUM *bn = NULL; BIO *bio = NULL; // 生成RSA密钥对 keys->public_key = RSA_new(); keys->private_key = RSA_new(); bn = BN_new(); ret = BN_set_word(bn, PUB_EXP); ret = RSA_generate_key_ex(keys->public_key, KEY_LENGTH, bn, NULL); ret = RSA_generate_key_ex(keys->private_key, KEY_LENGTH, bn, NULL); // 清除内存 BN_free(bn); return ret; } // RSA加密函数 int rsa_encrypt(char *input, int input_len, char *output, rsa_keys *keys) { int ret = 0; BIO *bio = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; size_t output_len = 0; // 获取RSA公钥 pkey = EVP_PKEY_new(); ret = EVP_PKEY_set1_RSA(pkey, keys->public_key); // 创建RSA加密上下文 ctx = EVP_PKEY_CTX_new(pkey, NULL); // 初始化RSA加密上下文 ret = EVP_PKEY_encrypt_init(ctx); // 设置RSA加密填充模式 ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); // 执行RSA加密 ret = EVP_PKEY_encrypt(ctx, NULL, &output_len, input, input_len); // 申请内存 output = (char*) malloc(output_len); // 执行RSA加密 ret = EVP_PKEY_encrypt(ctx, output, &output_len, input, input_len); // 清除内存 EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); return ret; } // RSA解密函数 int rsa_decrypt(char *input, int input_len, char *output, rsa_keys *keys) { int ret = 0; BIO *bio = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; size_t output_len = 0; // 获取RSA私钥 pkey = EVP_PKEY_new(); ret = EVP_PKEY_set1_RSA(pkey, keys->private_key); // 创建RSA解密上下文 ctx = EVP_PKEY_CTX_new(pkey, NULL); // 初始化RSA解密上下文 ret = EVP_PKEY_decrypt_init(ctx); // 设置RSA解密填充模式 ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); // 执行RSA解密 ret = EVP_PKEY_decrypt(ctx, NULL, &output_len, input, input_len); // 申请内存 output = (char*) malloc(output_len); // 执行RSA解密 ret = EVP_PKEY_decrypt(ctx, output, &output_len, input, input_len); // 清除内存 EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); return ret; } int main() { rsa_keys keys; char *input = "Hello, RSA!"; char *encrypted = NULL; char *decrypted = NULL; int ret = 0; // 生成RSA密钥对 ret = generate_rsa_keys(&keys); // RSA加密 ret = rsa_encrypt(input, strlen(input), encrypted, &keys); // RSA解密 ret = rsa_decrypt(encrypted, strlen(encrypted), decrypted, &keys); // 输出结果 printf("Input: %s\n", input); printf("Encrypted: %s\n", encrypted); printf("Decrypted: %s\n", decrypted); // 清除内存 free(encrypted); free(decrypted); return 0; } ``` 注释已经标注在代码中,主要分为以下几个部分: - 生成RSA密钥对 - RSA加密 - RSA解密 代码中使用OpenSSL库提供的RSA相关函数。首先使用`RSA_new()`函数创建RSA密钥对结构体,然后使用`RSA_generate_key_ex()`函数生成RSA密钥对。生成RSA密钥对后,使用`EVP_PKEY_set1_RSA()`函数获取RSA公钥或私钥,使用`EVP_PKEY_CTX_new()`函数创建RSA加密或解密上下文,使用`EVP_PKEY_encrypt()`或`EVP_PKEY_decrypt()`函数执行RSA加密或解密,最后使用`EVP_PKEY_CTX_free()`和`EVP_PKEY_free()`函数清除内存。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值