逆向-RSA加密

  • RSA (三個人的名字)非對稱加密!(現(xiàn)代加密算法)
    • 原根
    • 歐拉函數(shù)、歐拉定理(費馬小定)
    • 模反元素
    • m ^(e * d)mod n ≡ m
    • 迪菲赫爾曼密鑰交換
  • RSA算法
    • RSA:拆解兩個(大)質(zhì)數(shù)的乘積很難他匪!所以RSA相對安全Bハā!
    • 加密:M ^ e % N = C
    • 解密:C ^ d % N = M
    • 密文:C 明文: M
    • 公鑰:N 和 E
    • 私鑰:N 和 D
    • 條件(總共有6個數(shù)字!):
      • N 是由兩個很大的質(zhì)數(shù)(P1、P2)相乘得到!為了方便求出φ(N)笋粟。
      • D 是 E (65537) 相對于φ(N)的模反元素

由于Mac系統(tǒng)內(nèi)置OpenSSL(開源加密庫),所以在mac的終端可以直接使用OpenSSl玩RSA析蝴,OpenSSL中RSA算法常用命令有3個

命令 含義
genrsa 生成并輸入一個RSA私鑰
rsautl 使用RSA密鑰進行加密害捕、解密、簽名和驗證等運算
rsa 處理RSA密鑰的格式轉(zhuǎn)換等問題

終端演示

  • 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盾沫、將私鑰轉(zhuǎn)換為明文

    • 命令: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裁赠、通過公鑰加密數(shù)據(jù),私鑰解密數(shù)據(jù)

  • 生成明文文件: message.txt

  • 查看文件內(nèi)容: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、通過私鑰加密數(shù)據(jù)蕾哟,公鑰解密數(shù)據(jù)

  • 通過私鑰進行加密(簽名): 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一忱、通過私鑰加密數(shù)據(jù),公鑰解密數(shù)據(jù)
  • 通過私鑰進行加密(簽名): 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代碼演示

前提:準(zhǔn)備好公鑰谭确、私鑰帘营,需要在終端生成(屬于自己簽名)

證書申請步驟

  • 1、申請CSR文件:keychain -> 證書助理 -> 從證書頒發(fā)機構(gòu)請求證書

  • 2逐哈、生成CSR請求文件(證書頒發(fā)機構(gòu)信息 + 公鑰)

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

      image
  • 3、生成CRT證書(自己簽名昂秃,沒有認(rèn)證的)

    • 命令: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編碼后,文件數(shù)量變多哗戈,不適合對大型數(shù)據(jù)進行編碼

  3. bse64和數(shù)據(jù)是一一對應(yīng)的

RSA代碼

前提:通過證書申請步驟,準(zhǔn)備好p12和der文件

  • 1荷科、創(chuàng)建RSA加解密類:RSACryptor
<!--RSACryptor.h-->
#import <Foundation/Foundation.h>

@interface RSACryptor : NSObject

+ (instancetype)sharedRSACryptor;

    /**
     *  生成密鑰對
     *
     *  @param keySize 密鑰尺寸唯咬,可選數(shù)值(512/1024/2048)
     */
- (void)generateKeyPair:(NSUInteger)keySize;

    /**
     *  加載公鑰
     *
     *  @param publicKeyPath 公鑰路徑
     *
     @code
     # 生成證書
     $ openssl genrsa -out ca.key 1024
     # 創(chuàng)建證書請求
     $ openssl req -new -key ca.key -out rsacert.csr
     # 生成證書并簽名
     $ openssl x509 -req -days 3650 -in rsacert.csr -signkey ca.key -out rsacert.crt
     # 轉(zhuǎn)換格式
     $ 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;

    /**
     *  加密數(shù)據(jù)
     *
     *  @param plainData 明文數(shù)據(jù)
     *
     *  @return 密文數(shù)據(jù)
     */
- (NSData *)encryptData:(NSData *)plainData;

    /**
     *  解密數(shù)據(jù)
     *
     *  @param cipherData 密文數(shù)據(jù)
     *
     *  @return 明文數(shù)據(jù)
     */
- (NSData *)decryptData:(NSData *)cipherData;
@end

<!--RSACryptor.m-->
#import "RSACryptor.h"

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

// 公鑰/私鑰標(biāo)簽
#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;        // 公鑰標(biāo)簽
    @property (nonatomic, retain) NSData *privateTag;       // 私鑰標(biāo)簽

    @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) {
        // 查詢密鑰的標(biāo)簽
        _privateTag = [[NSData alloc] initWithBytes:privateKeyIdentifier length:sizeof(privateKeyIdentifier)];
        _publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
    }
    return self;
}

#pragma mark - 加密 & 解密數(shù)據(jù)
- (NSData *)encryptData:(NSData *)plainData {
    OSStatus sanityCheck = noErr;
    size_t cipherBufferSize = 0;
    size_t keyBufferSize = 0;

    NSAssert(plainData != nil, @"明文數(shù)據(jù)為空");
    NSAssert(publicKeyRef != nil, @"公鑰為空");

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

    // 計算緩沖區(qū)大小
    cipherBufferSize = SecKeyGetBlockSize(publicKeyRef);
    keyBufferSize = [plainData length];

    if (kTypeOfWrapPadding == kSecPaddingNone) {
        NSAssert(keyBufferSize <= cipherBufferSize, @"加密內(nèi)容太大");
    } else {
        NSAssert(keyBufferSize <= (cipherBufferSize - 11), @"加密內(nèi)容太大");
    }

    // 分配緩沖區(qū)
    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);

    // 生成密文數(shù)據(jù)
    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, @"私鑰不存在");

    // 計算緩沖區(qū)大小
    cipherBufferSize = SecKeyGetBlockSize(privateKey);
    keyBufferSize = [cipherData length];

    NSAssert(keyBufferSize <= cipherBufferSize, @"解密內(nèi)容太大");

    // 分配緩沖區(qū)
    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);

    // 生成明文數(shù)據(jù)
    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);

    // 刪除當(dāng)前密鑰對
    [self deleteAsymmetricKeys];

    // 容器字典
    NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];
    NSMutableDictionary *publicKeyAttr = [[NSMutableDictionary alloc] init];
    NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];

    // 設(shè)置密鑰對的頂級字典
    [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];

    // 設(shè)置私鑰字典
    [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
    [privateKeyAttr setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];

    // 設(shè)置公鑰字典
    [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
    [publicKeyAttr setObject:_publicTag forKey:(__bridge id)kSecAttrApplicationTag];

    // 設(shè)置頂級字典屬性
    [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, @"公鑰路徑為空");

    // 刪除當(dāng)前公鑰
    if (publicKeyRef) CFRelease(publicKeyRef);

    // 從一個 DER 表示的證書創(chuàng)建一個證書對象
    NSData *certificateData = [NSData dataWithContentsOfFile:publicKeyPath];
    SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
    NSAssert(certificateRef != NULL, @"公鑰文件錯誤");

    // 返回一個默認(rèn) X509 策略的公鑰對象胆胰,使用之后需要調(diào)用 CFRelease 釋放
    SecPolicyRef policyRef = SecPolicyCreateBasicX509();
    // 包含信任管理信息的結(jié)構(gòu)體
    SecTrustRef trustRef;

    // 基于證書和策略創(chuàng)建一個信任管理對象
    OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);
    NSAssert(status == errSecSuccess, @"創(chuàng)建信任管理對象失敗");

    // 信任結(jié)果
    SecTrustResultType trustResult;
    // 評估指定證書和策略的信任管理是否有效
    status = SecTrustEvaluate(trustRef, &trustResult);
    NSAssert(status == errSecSuccess, @"信任評估失敗");

    // 評估之后返回公鑰子證書
    publicKeyRef = SecTrustCopyPublicKey(trustRef);
    NSAssert(publicKeyRef != NULL, @"公鑰創(chuàng)建失敗");

    if (certificateRef) CFRelease(certificateRef);
    if (policyRef) CFRelease(policyRef);
    if (trustRef) CFRelease(trustRef);
}

    /**
     *  加載私鑰
     */
- (void)loadPrivateKey:(NSString *)privateKeyPath password:(NSString *)password {

    NSAssert(privateKeyPath.length != 0, @"私鑰路徑為空");

    // 刪除當(dāng)前私鑰
    if (privateKeyRef) CFRelease(privateKeyRef);

    NSData *PKCS12Data = [NSData dataWithContentsOfFile:privateKeyPath];
    CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
    CFStringRef passwordRef = (__bridge CFStringRef)password;

    // 從 PKCS #12 證書中提取標(biāo)示和證書
    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 格式數(shù)據(jù)中的標(biāo)示和證書
    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, @"私鑰創(chuàng)建失敗");
}

    /**
     *  刪除非對稱密鑰
     */
- (void)deleteAsymmetricKeys {
    OSStatus sanityCheck = noErr;
    NSMutableDictionary *queryPublicKey = [[NSMutableDictionary alloc] init];
    NSMutableDictionary *queryPrivateKey = [[NSMutableDictionary alloc] init];

    // 設(shè)置公鑰查詢字典
    [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];

    // 設(shè)置私鑰查詢字典
    [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];

        // 設(shè)置私鑰查詢字典
        [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]);
}

<!--打印結(jié)果-->
en - L+1uUQ9eSzZmVJuEXMZ7Z8Wr241ze/6XbKMoBTLDdCvlf2bLcJPDJor5RVvn00rPg65NLwd3AyZDy+4/3t41bAJtHo2+MjmAHJ32rmTTx/HH5B3WOghOGqhLZS1hLFt62tic8betewTgzJg9IvMbtSvXDl4XdgLXM8ZWFdosneg=
de - hello

從結(jié)果中可以發(fā)現(xiàn),每次RSA加密結(jié)果不一樣沐兵,原因是因為RSA有個填充模式别垮,導(dǎo)致每次結(jié)果不一樣

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

  • kSecPaddingPKCS1 填充扎谎,密文隨機變化

    image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碳想,一起剝皮案震驚了整個濱河市烧董,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胧奔,老刑警劉巖逊移,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異龙填,居然都是意外死亡螟左,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門觅够,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胶背,“玉大人,你說我怎么就攤上這事喘先∏鳎” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵窘拯,是天一觀的道長红且。 經(jīng)常有香客問我,道長涤姊,這世上最難降的妖魔是什么暇番? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮思喊,結(jié)果婚禮上壁酬,老公的妹妹穿的比我還像新娘。我一直安慰自己恨课,他們只是感情好舆乔,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著剂公,像睡著了一般希俩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纲辽,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天颜武,我揣著相機與錄音,去河邊找鬼拖吼。 笑死鳞上,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绿贞。 我是一名探鬼主播因块,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼籍铁!你這毒婦竟也來了涡上?” 一聲冷哼從身側(cè)響起趾断,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吩愧,沒想到半個月后芋酌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡雁佳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年脐帝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糖权。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡堵腹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出星澳,到底是詐尸還是另有隱情疚顷,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布禁偎,位于F島的核電站腿堤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏如暖。R本人自食惡果不足惜笆檀,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盒至。 院中可真熱鬧酗洒,春花似錦、人聲如沸妄迁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽登淘。三九已至,卻和暖如春封字,著一層夾襖步出監(jiān)牢的瞬間黔州,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工阔籽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留流妻,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓笆制,卻偏偏與公主長得像绅这,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子在辆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容