美文网首页
逆向-RSA加密

逆向-RSA加密

作者: Mjs | 来源:发表于2021-06-01 13:53 被阅读0次
    • RSA (三个人的名字)非对称加密!(现代加密算法)
      • 原根
      • 欧拉函数、欧拉定理(费马小定)
      • 模反元素
      • m ^(e * d)mod n ≡ m
      • 迪菲赫尔曼密钥交换
    • RSA算法
      • RSA:拆解两个(大)质数的乘积很难!所以RSA相对安全!!
      • 加密:M ^ e % N = C
      • 解密:C ^ d % N = M
      • 密文:C 明文: M
      • 公钥:N 和 E
      • 私钥:N 和 D
      • 条件(总共有6个数字!):
        • N 是由两个很大的质数(P1、P2)相乘得到!为了方便求出φ(N)。
        • D 是 E (65537) 相对于φ(N)的模反元素

    由于Mac系统内置OpenSSL(开源加密库),所以在mac的终端可以直接使用OpenSSl玩RSA,OpenSSL中RSA算法常用命令有3个

    命令 含义
    genrsa 生成并输入一个RSA私钥
    rsautl 使用RSA密钥进行加密、解密、签名和验证等运算
    rsa 处理RSA密钥的格式转换等问题

    终端演示

    • 1、生成RSA私钥,密钥成都为1024bit

      • 命令:openssl genrsa -out private.pem 1024

      • 查看 cat private.pem文件,其中是base64编码

    -----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQClnyEAq+wUiAB2edcfK2Yfo/3budcPRzPEPrbBv18TkTqyCla6
    mC+wOut6kPY40n691V5K2cJ4jPfCSdOBUTcizRGuWfvto2Rh46mYLzU7eW6hpF/L
    yhbSoHkfU2k71ufJWUtW15tYZ0By+LTlfBArZbrMYDm+Lpsay0bH9AGe+QIDAQAB
    AoGBAJLVtNW6lpBRT0+6j72DpYPRyYQfjApwjvWiwDafqvRXIpmsTt4ZhNYSNqkw
    kgsom9NDsthbnW1xVUs8VrbkwSK8iGzpObdio744rVzzUArV2+n4bHG8Ko8mFlgG
    2e0+/YkfxG/ewX58XqJo0KLJPHzXkIYYHFiCrTevDqT8LCABAkEA3E2z911SIHOW
    Cf9d6yAa06WaD2v7hL4r3GnwR9wlk86JtsasdxfloD02coT2liZ24m6PCCUojyn4
    5S5wQ+MEAQJBAMB1MWdzPKCcHlvl/ea09TJFS9rxnCDCAWy0U+nVG0Nj8CQZhdVC
    35eamHvLGZaNKEwO/mbp0mGLLc1yV9NKuvkCQHsmKJL/pLglRNsj2EFmefiT2vIB
    /+CtWeFliv7wjkT4sLzuhFwyjJctgLE1qI44xD5BZU09UFXvNYYPlowsbAECQQC9
    5mU7KG/YInOqRgQD0uZmFg5FGUXu5L83Ha/2+HoQQto/JJfz2Cp7kuWGsN6suNfc
    RKctsOYPrZ8iKwMRz5kxAkAx4MXLDPPUZ2P7yFncGbvMkhyG/Ok5njTmyJkSwdF6
    sIkaqAb+ZOkc/UBd6C5IUgrHwgK0lbq0QuzhA0GtpDl0
    -----END RSA PRIVATE KEY-----
    

    2、从私钥中提取公钥(即 n和e)

    • 命令:openssl rsa -in private.pem -pubout -out public.pem
    • 查看公钥:cat public.pem
    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClnyEAq+wUiAB2edcfK2Yfo/3b
    udcPRzPEPrbBv18TkTqyCla6mC+wOut6kPY40n691V5K2cJ4jPfCSdOBUTcizRGu
    Wfvto2Rh46mYLzU7eW6hpF/LyhbSoHkfU2k71ufJWUtW15tYZ0By+LTlfBArZbrM
    YDm+Lpsay0bH9AGe+QIDAQAB
    -----END PUBLIC KEY-----
    
    • 3、将私钥转换为明文

      • 命令:openssl rsa -in private.pem -text -out private.txt
    modulus:
        00:a5:9f:21:00:ab:ec:14:88:00:76:79:d7:1f:2b:
        66:1f:a3:fd:db:b9:d7:0f:47:33:c4:3e:b6:c1:bf:
        5f:13:91:3a:b2:0a:56:ba:98:2f:b0:3a:eb:7a:90:
        f6:38:d2:7e:bd:d5:5e:4a:d9:c2:78:8c:f7:c2:49:
        d3:81:51:37:22:cd:11:ae:59:fb:ed:a3:64:61:e3:
        a9:98:2f:35:3b:79:6e:a1:a4:5f:cb:ca:16:d2:a0:
        79:1f:53:69:3b:d6:e7:c9:59:4b:56:d7:9b:58:67:
        40:72:f8:b4:e5:7c:10:2b:65:ba:cc:60:39:be:2e:
        9b:1a:cb:46:c7:f4:01:9e:f9
    publicExponent: 65537 (0x10001)
    privateExponent:
        00:92:d5:b4:d5:ba:96:90:51:4f:4f:ba:8f:bd:83:
        a5:83:d1:c9:84:1f:8c:0a:70:8e:f5:a2:c0:36:9f:
        aa:f4:57:22:99:ac:4e:de:19:84:d6:12:36:a9:30:
        92:0b:28:9b:d3:43:b2:d8:5b:9d:6d:71:55:4b:3c:
        56:b6:e4:c1:22:bc:88:6c:e9:39:b7:62:a3:be:38:
        ad:5c:f3:50:0a:d5:db:e9:f8:6c:71:bc:2a:8f:26:
        16:58:06:d9:ed:3e:fd:89:1f:c4:6f:de:c1:7e:7c:
        5e:a2:68:d0:a2:c9:3c:7c:d7:90:86:18:1c:58:82:
        ad:37:af:0e:a4:fc:2c:20:01
    prime1:
        00:dc:4d:b3:f7:5d:52:20:73:96:09:ff:5d:eb:20:
        1a:d3:a5:9a:0f:6b:fb:84:be:2b:dc:69:f0:47:dc:
        25:93:ce:89:b6:c6:ac:77:17:e5:a0:3d:36:72:84:
        f6:96:26:76:e2:6e:8f:08:25:28:8f:29:f8:e5:2e:
        70:43:e3:04:01
    prime2:
        00:c0:75:31:67:73:3c:a0:9c:1e:5b:e5:fd:e6:b4:
        f5:32:45:4b:da:f1:9c:20:c2:01:6c:b4:53:e9:d5:
        1b:43:63:f0:24:19:85:d5:42:df:97:9a:98:7b:cb:
        19:96:8d:28:4c:0e:fe:66:e9:d2:61:8b:2d:cd:72:
        57:d3:4a:ba:f9
    exponent1:
        7b:26:28:92:ff:a4:b8:25:44:db:23:d8:41:66:79:
        f8:93:da:f2:01:ff:e0:ad:59:e1:65:8a:fe:f0:8e:
        44:f8:b0:bc:ee:84:5c:32:8c:97:2d:80:b1:35:a8:
        8e:38:c4:3e:41:65:4d:3d:50:55:ef:35:86:0f:96:
        8c:2c:6c:01
    exponent2:
        00:bd:e6:65:3b:28:6f:d8:22:73:aa:46:04:03:d2:
        e6:66:16:0e:45:19:45:ee:e4:bf:37:1d:af:f6:f8:
        7a:10:42:da:3f:24:97:f3:d8:2a:7b:92:e5:86:b0:
        de:ac:b8:d7:dc:44:a7:2d:b0:e6:0f:ad:9f:22:2b:
        03:11:cf:99:31
    coefficient:
        31:e0:c5:cb:0c:f3:d4:67:63:fb:c8:59:dc:19:bb:
        cc:92:1c:86:fc:e9:39:9e:34:e6:c8:99:12:c1:d1:
        7a:b0:89:1a:a8:06:fe:64:e9:1c:fd:40:5d:e8:2e:
        48:52:0a:c7:c2:02:b4:95:ba:b4:42:ec:e1:03:41:
        ad:a4:39:74
    -----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQClnyEAq+wUiAB2edcfK2Yfo/3budcPRzPEPrbBv18TkTqyCla6
    mC+wOut6kPY40n691V5K2cJ4jPfCSdOBUTcizRGuWfvto2Rh46mYLzU7eW6hpF/L
    yhbSoHkfU2k71ufJWUtW15tYZ0By+LTlfBArZbrMYDm+Lpsay0bH9AGe+QIDAQAB
    AoGBAJLVtNW6lpBRT0+6j72DpYPRyYQfjApwjvWiwDafqvRXIpmsTt4ZhNYSNqkw
    kgsom9NDsthbnW1xVUs8VrbkwSK8iGzpObdio744rVzzUArV2+n4bHG8Ko8mFlgG
    2e0+/YkfxG/ewX58XqJo0KLJPHzXkIYYHFiCrTevDqT8LCABAkEA3E2z911SIHOW
    Cf9d6yAa06WaD2v7hL4r3GnwR9wlk86JtsasdxfloD02coT2liZ24m6PCCUojyn4
    5S5wQ+MEAQJBAMB1MWdzPKCcHlvl/ea09TJFS9rxnCDCAWy0U+nVG0Nj8CQZhdVC
    35eamHvLGZaNKEwO/mbp0mGLLc1yV9NKuvkCQHsmKJL/pLglRNsj2EFmefiT2vIB
    /+CtWeFliv7wjkT4sLzuhFwyjJctgLE1qI44xD5BZU09UFXvNYYPlowsbAECQQC9
    5mU7KG/YInOqRgQD0uZmFg5FGUXu5L83Ha/2+HoQQto/JJfz2Cp7kuWGsN6suNfc
    RKctsOYPrZ8iKwMRz5kxAkAx4MXLDPPUZ2P7yFncGbvMkhyG/Ok5njTmyJkSwdF6
    sIkaqAb+ZOkc/UBd6C5IUgrHwgK0lbq0QuzhA0GtpDl0
    -----END RSA PRIVATE KEY-----
    
    • 4、通过公钥加密数据,私钥解密数据

    • 生成明文文件: message.txt

    • 查看文件内容:cat message.txt

    • 通过公钥进行加密:openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out enc.txt,生成的文件是二级制文件,无法打开。

    • 通过私钥进行解密:openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt

    • 5、通过私钥加密数据,公钥解密数据

    • 通过私钥进行加密(签名): openssl rsautl -sign -in message.txt -inkey private.pem -out enc.txt

    • 通过公钥进行解密(验证):openssl rsautl -verify -in enc.txt -inkey public.pem -pubin -out dec.txt

    • 通过公钥进行加密:openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out enc.txt

    • 通过私钥进行解密:openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt
      生成的文件如下所示

      image
      • 6、通过私钥加密数据,公钥解密数据
    • 通过私钥进行加密(签名): openssl rsautl -sign -in message.txt -inkey private.pem -out enc.txt

    • 通过公钥进行解密(验证):openssl rsautl -verify -in enc.txt -inkey public.pem -pubin -out dec.txt

    RSA代码演示

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

    证书申请步骤

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

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

      • 命令:openssl req -new -key private.pem -out rsacert.csr
        (然后按信息填写信息,密码可不填)

        image
    • 3、生成CRT证书(自己签名,没有认证的)

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

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

        image
    • 5、获取p12文件

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

        image

        注:代码中使用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

    代码演示

    //编码
    - (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];
    }
    
    base64说明
    1. base64只适用于表示二进制文件

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

    3. bse64和数据是一一对应的

    RSA代码

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

    • 1、创建RSA加解密类:RSACryptor
    <!--RSACryptor.h-->
    #import <Foundation/Foundation.h>
    
    @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
    
    <!--RSACryptor.m-->
    #import "RSACryptor.h"
    
    // 填充模式
    /*
     - kSecPaddingNone 不填充
     - kSecPaddingPKCS1 填充
     */
    #define kTypeOfWrapPadding        kSecPaddingPKCS1
    
    // 公钥/私钥标签
    #define kPublicKeyTag            "com.jsc.EncryptDemo.publickey"
    #define kPrivateKeyTag            "com.jsc.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 <= cipherBufferSize, @"加密内容太大");
        } else {
            NSAssert(keyBufferSize <= (cipherBufferSize - 11), @"加密内容太大");
        }
    
        // 分配缓冲区
        cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
        memset((void *)cipherBuffer, 0x0, cipherBufferSize);
    
        // 使用公钥加密
        sanityCheck = SecKeyEncrypt(publicKeyRef,
                                    kTypeOfWrapPadding,
                                    (const uint8_t *)[plainData bytes],
                                    keyBufferSize,
                                    cipherBuffer,
                                    &cipherBufferSize
                                    );
    
        NSAssert(sanityCheck == noErr, @"加密错误,OSStatus == %d", sanityCheck);
    
        // 生成密文数据
        cipher = [NSData dataWithBytes:(const void *)cipherBuffer length:(NSUInteger)cipherBufferSize];
    
        if (cipherBuffer) free(cipherBuffer);
    
        return cipher;
    }
    
    - (NSData *)decryptData:(NSData *)cipherData {
        OSStatus sanityCheck = noErr;
        size_t cipherBufferSize = 0;
        size_t keyBufferSize = 0;
    
        NSData *key = nil;
        uint8_t *keyBuffer = NULL;
    
        SecKeyRef privateKey = NULL;
    
        privateKey = [self getPrivateKeyRef];
        NSAssert(privateKey != NULL, @"私钥不存在");
    
        // 计算缓冲区大小
        cipherBufferSize = SecKeyGetBlockSize(privateKey);
        keyBufferSize = [cipherData length];
    
        NSAssert(keyBufferSize <= cipherBufferSize, @"解密内容太大");
    
        // 分配缓冲区
        keyBuffer = malloc(keyBufferSize * sizeof(uint8_t));
        memset((void *)keyBuffer, 0x0, keyBufferSize);
    
        // 使用私钥解密
        sanityCheck = SecKeyDecrypt(privateKey,
                                    kTypeOfWrapPadding,
                                    (const uint8_t *)[cipherData bytes],
                                    cipherBufferSize,
                                    keyBuffer,
                                    &keyBufferSize
                                    );
    
        NSAssert1(sanityCheck == noErr, @"解密错误,OSStatus == %d", sanityCheck);
    
        // 生成明文数据
        key = [NSData dataWithBytes:(const void *)keyBuffer length:(NSUInteger)keyBufferSize];
    
        if (keyBuffer) free(keyBuffer);
    
        return key;
    }
    
    #pragma mark - 密钥处理
        /**
         *  生成密钥对
         */
    - (void)generateKeyPair:(NSUInteger)keySize {
        OSStatus sanityCheck = noErr;
        publicKeyRef = NULL;
        privateKeyRef = NULL;
    
        NSAssert1((keySize == 512 || keySize == 1024 || keySize == 2048), @"密钥尺寸无效 %tu", keySize);
    
        // 删除当前密钥对
        [self deleteAsymmetricKeys];
    
        // 容器字典
        NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *publicKeyAttr = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];
    
        // 设置密钥对的顶级字典
        [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
        [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];
    
        // 设置私钥字典
        [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
        [privateKeyAttr setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
    
        // 设置公钥字典
        [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
        [publicKeyAttr setObject:_publicTag forKey:(__bridge id)kSecAttrApplicationTag];
    
        // 设置顶级字典属性
        [keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
        [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];
    
        // SecKeyGeneratePair 返回密钥对引用
        sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef);
        NSAssert((sanityCheck == noErr && publicKeyRef != NULL && privateKeyRef != NULL), @"生成密钥对失败");
    }
    
        /**
         *  加载公钥
         */
    - (void)loadPublicKey:(NSString *)publicKeyPath {
    
        NSAssert(publicKeyPath.length != 0, @"公钥路径为空");
    
        // 删除当前公钥
        if (publicKeyRef) CFRelease(publicKeyRef);
    
        // 从一个 DER 表示的证书创建一个证书对象
        NSData *certificateData = [NSData dataWithContentsOfFile:publicKeyPath];
        SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
        NSAssert(certificateRef != NULL, @"公钥文件错误");
    
        // 返回一个默认 X509 策略的公钥对象,使用之后需要调用 CFRelease 释放
        SecPolicyRef policyRef = SecPolicyCreateBasicX509();
        // 包含信任管理信息的结构体
        SecTrustRef trustRef;
    
        // 基于证书和策略创建一个信任管理对象
        OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);
        NSAssert(status == errSecSuccess, @"创建信任管理对象失败");
    
        // 信任结果
        SecTrustResultType trustResult;
        // 评估指定证书和策略的信任管理是否有效
        status = SecTrustEvaluate(trustRef, &trustResult);
        NSAssert(status == errSecSuccess, @"信任评估失败");
    
        // 评估之后返回公钥子证书
        publicKeyRef = SecTrustCopyPublicKey(trustRef);
        NSAssert(publicKeyRef != NULL, @"公钥创建失败");
    
        if (certificateRef) CFRelease(certificateRef);
        if (policyRef) CFRelease(policyRef);
        if (trustRef) CFRelease(trustRef);
    }
    
        /**
         *  加载私钥
         */
    - (void)loadPrivateKey:(NSString *)privateKeyPath password:(NSString *)password {
    
        NSAssert(privateKeyPath.length != 0, @"私钥路径为空");
    
        // 删除当前私钥
        if (privateKeyRef) CFRelease(privateKeyRef);
    
        NSData *PKCS12Data = [NSData dataWithContentsOfFile:privateKeyPath];
        CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
        CFStringRef passwordRef = (__bridge CFStringRef)password;
    
        // 从 PKCS #12 证书中提取标示和证书
        SecIdentityRef myIdentity;
        SecTrustRef myTrust;
        const void *keys[] =   {kSecImportExportPassphrase};
        const void *values[] = {passwordRef};
        CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
        CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    
        // 返回 PKCS #12 格式数据中的标示和证书
        OSStatus status = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
    
        if (status == noErr) {
            CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
            myIdentity = (SecIdentityRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
            myTrust = (SecTrustRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
        }
    
        if (optionsDictionary) CFRelease(optionsDictionary);
    
        NSAssert(status == noErr, @"提取身份和信任失败");
    
        SecTrustResultType trustResult;
        // 评估指定证书和策略的信任管理是否有效
        status = SecTrustEvaluate(myTrust, &trustResult);
        NSAssert(status == errSecSuccess, @"信任评估失败");
    
        // 提取私钥
        status = SecIdentityCopyPrivateKey(myIdentity, &privateKeyRef);
        NSAssert(status == errSecSuccess, @"私钥创建失败");
    }
    
        /**
         *  删除非对称密钥
         */
    - (void)deleteAsymmetricKeys {
        OSStatus sanityCheck = noErr;
        NSMutableDictionary *queryPublicKey = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *queryPrivateKey = [[NSMutableDictionary alloc] init];
    
        // 设置公钥查询字典
        [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
        [queryPublicKey setObject:_publicTag forKey:(__bridge id)kSecAttrApplicationTag];
        [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    
        // 设置私钥查询字典
        [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
        [queryPrivateKey setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
        [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    
        // 删除私钥
        sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPrivateKey);
        NSAssert1((sanityCheck == noErr || sanityCheck == errSecItemNotFound), @"删除私钥错误,OSStatus == %d", sanityCheck);
    
        // 删除公钥
        sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPublicKey);
        NSAssert1((sanityCheck == noErr || sanityCheck == errSecItemNotFound), @"删除公钥错误,OSStatus == %d", sanityCheck);
    
        if (publicKeyRef) CFRelease(publicKeyRef);
        if (privateKeyRef) CFRelease(privateKeyRef);
    }
    
        /**
         *  获得私钥引用
         */
    - (SecKeyRef)getPrivateKeyRef {
        OSStatus sanityCheck = noErr;
        SecKeyRef privateKeyReference = NULL;
    
        if (privateKeyRef == NULL) {
            NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init];
    
            // 设置私钥查询字典
            [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
            [queryPrivateKey setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
            [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
            [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    
            // 获得密钥
            sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKeyReference);
    
            if (sanityCheck != noErr) {
                privateKeyReference = NULL;
            }
        } else {
            privateKeyReference = privateKeyRef;
        }
    
        return privateKeyReference;
    }
    @end
    
    
    • 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<UITouch *> *)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 填充,密文随机变化

      image

    相关文章

      网友评论

          本文标题:逆向-RSA加密

          本文链接:https://www.haomeiwen.com/subject/stbrsltx.html