iOS逆向之RSA加密(下)

时间:2021-7-3 作者:qvyue

本文主要介绍RSA的代码演示过程

iOS逆向之RSA加密(下)

RSA代码演示

前提:准备好公钥、私钥,需要在终端生成(属于自己签名)

另外作为开发者我总结了很多iOS进阶学习用到的文件视频等等资源,可以:点击领取

证书申请步骤

  • 1、申请CSR文件:keychain -> 证书助理 -> 从证书颁发机构请求证书

  • 2、生成CSR请求文件(证书颁发机构信息 + 公钥)

    • 命令:openssl req -new -key private.pem -out rsacert.csr

      iOS逆向之RSA加密(下)
  • 3、生成CRT证书(自己签名,没有认证的)

    • 命令:openssl x509 -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
  • 4、生成der文件

    • 命令:openssl x509 -outform der -in rsacert.crt -out rsacert.der

      iOS逆向之RSA加密(下)
  • 5、获取p12文件

    • 命令:openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt

      iOS逆向之RSA加密(下)

      注:代码中使用der格式

base64编码

base64编码由0-9、a-z、A-Z + /(64个字符 )加上 =(表示补零) 来组成的文本

终端命令

  • vi message.txt

  • base64编码:base64 message.txt -o abc.txt

  • base64解码:base abc.txt -o 123.txt -D

代码演示

- (void)viewDidLoad {
    [super viewDidLoad];

    NSLog(@"en:%@", [self base64Encode:@"A"]);
    NSLog(@"de:%@", [self base64Decode:@"QQ=="]);

}

//编码
- (NSString *)base64Encode:(NSString *)string{
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    return [data base64EncodedStringWithOptions: 0];
}
//解码
- (NSString *)base64Decode:(NSString *)string{
    NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}


en:QQ==
de:A

base64说明

  • 1、base64只适用于表示二进制文件

  • 2、base64编码后,文件数量变多,不适合对大型数据进行编码

  • 3、bse64和数据是一一对应

代码演示

前提:通过证书申请步骤,准备好p12和der文件

  • 1、创建RSA加解密类:RSACryptor

#import 

@interface RSACryptor : NSObject

+ (instancetype)sharedRSACryptor;

    /**
     *  生成密钥对
     *
     *  @param keySize 密钥尺寸,可选数值(512/1024/2048)
     */
- (void)generateKeyPair:(NSUInteger)keySize;

    /**
     *  加载公钥
     *
     *  @param publicKeyPath 公钥路径
     *
     @code
     # 生成证书
     $ openssl genrsa -out ca.key 1024
     # 创建证书请求
     $ openssl req -new -key ca.key -out rsacert.csr
     # 生成证书并签名
     $ openssl x509 -req -days 3650 -in rsacert.csr -signkey ca.key -out rsacert.crt
     # 转换格式
     $ openssl x509 -outform der -in rsacert.crt -out rsacert.der
     @endcode
     */
- (void)loadPublicKey:(NSString *)publicKeyPath;

    /**
     *  加载私钥
     *
     *  @param privateKeyPath p12文件路径
     *  @param password       p12文件密码
     *
     @code
     openssl pkcs12 -export -out p.p12 -inkey ca.key -in rsacert.crt
     @endcode
     */
- (void)loadPrivateKey:(NSString *)privateKeyPath password:(NSString *)password;

    /**
     *  加密数据
     *
     *  @param plainData 明文数据
     *
     *  @return 密文数据
     */
- (NSData *)encryptData:(NSData *)plainData;

    /**
     *  解密数据
     *
     *  @param cipherData 密文数据
     *
     *  @return 明文数据
     */
- (NSData *)decryptData:(NSData *)cipherData;
@end


#import "RSACryptor.h"

// 填充模式
/*
 - kSecPaddingNone 不填充
 - kSecPaddingPKCS1 填充
 */
#define kTypeOfWrapPadding        kSecPaddingPKCS1

// 公钥/私钥标签
#define kPublicKeyTag            "com.cjl.EncryptDemo.publickey"
#define kPrivateKeyTag            "com.cjl.EncryptDemo.privatekey"

static const uint8_t publicKeyIdentifier[]        = kPublicKeyTag;
static const uint8_t privateKeyIdentifier[]        = kPrivateKeyTag;

@interface RSACryptor() {
    SecKeyRef publicKeyRef;                             // 公钥引用
    SecKeyRef privateKeyRef;                            // 私钥引用
}

    @property (nonatomic, retain) NSData *publicTag;        // 公钥标签
    @property (nonatomic, retain) NSData *privateTag;       // 私钥标签

    @end

@implementation RSACryptor

+ (instancetype)sharedRSACryptor {
    static id instance;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        // 查询密钥的标签
        _privateTag = [[NSData alloc] initWithBytes:privateKeyIdentifier length:sizeof(privateKeyIdentifier)];
        _publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
    }
    return self;
}

#pragma mark - 加密 & 解密数据
- (NSData *)encryptData:(NSData *)plainData {
    OSStatus sanityCheck = noErr;
    size_t cipherBufferSize = 0;
    size_t keyBufferSize = 0;

    NSAssert(plainData != nil, @"明文数据为空");
    NSAssert(publicKeyRef != nil, @"公钥为空");

    NSData *cipher = nil;
    uint8_t *cipherBuffer = NULL;

    // 计算缓冲区大小
    cipherBufferSize = SecKeyGetBlockSize(publicKeyRef);
    keyBufferSize = [plainData length];

    if (kTypeOfWrapPadding == kSecPaddingNone) {
        NSAssert(keyBufferSize 
  • 2、通过代码加载公钥(der文件)和私钥(p12文件)
- (void)testRSA{
    //1、加载公钥
    [[RSACryptor sharedRSACryptor] loadPublicKey:[[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil]];

    //2、加载私钥
    [[RSACryptor sharedRSACryptor] loadPrivateKey:[[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil] password:@"123456"];
}

  • 3、使用RSA进行加解密
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    //加密
    NSData *result = [[RSACryptor sharedRSACryptor] encryptData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding]];
    NSString *base64 = [result base64EncodedStringWithOptions:0];
    NSLog(@"en - %@", base64);

    //解密
    NSData *jiemi = [[RSACryptor sharedRSACryptor] decryptData:result];
    NSLog(@"de - %@", [[NSString alloc] initWithData:jiemi encoding:NSUTF8StringEncoding]);
}


en - L+1uUQ9eSzZmVJuEXMZ7Z8Wr241ze/6XbKMoBTLDdCvlf2bLcJPDJor5RVvn00rPg65NLwd3AyZDy+4/3t41bAJtHo2+MjmAHJ32rmTTx/HH5B3WOghOGqhLZS1hLFt62tic8betewTgzJg9IvMbtSvXDl4XdgLXM8ZWFdosneg=
de - hello

从结果中可以发现,每次RSA加密结果不一样,原因是因为RSA有个填充模式,导致每次结果不一样

  • kSecPaddingNone 不填充,密文每次不变

  • kSecPaddingPKCS1 填充,密文随机变化

    iOS逆向之RSA加密(下)

总结

  • base64编码说明:

    • 1、base64只适用于表示二进制文件

    • 2、base64编码后,文件数量变多,不适合对大型数据进行编码

    • 3、bse64和数据是一一对应

  • RSA代码加解密是通过Security框架

    • 加密:使用SecKeyEncrypt函数

    • 解密:使用SecKeyDecrypt函数

    • 加密有两种填充模式:

      • kSecPaddingNone 不填充,密文每次不变

      • kSecPaddingPKCS1 填充,密文每次随机变化

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。