01:RSA 加密和原理 .pem .csr .crt .der .p12文件的區別 base64


復習:

1:rsa加密解密6個步驟,p、q、n、φ(n)、e、d

2: 加密理論:歐拉函數、歐拉定理、模反元素、迪菲赫爾曼秘鑰交換、RSA加解密

3:生成證書的步驟、證書的關系。

4:base64編解碼的目的:對於二進制數據不便於查看或者表示,所以用base64來編碼查看。cat、xxd命令

5:rsa填充模式:128字節-明文117字節。pkcs1

6:RSA用途及特點

特點:RSA加密相對比較安全,但是通過數學算法來加密和解密,效率比較低。

用途:所以一般RSA的主戰場是加密比較小的數據,比如對大數據進行對稱加密,再用RSA給對稱加密的KEY進行加密,或者加密Hash值,也就是數字簽名

 

目錄

一:RSA加密原理

二:RSA加密理論

三:終端openssl 公鑰加密,私鑰解密,私鑰簽名,公鑰驗證

四:生成證書 csr、crt、der公鑰證書、p12私鑰

五:base64編解碼

六:RSA代碼

七:base64代碼

 

正文-RSA

一:RSA加密的原理:

1:第一步,隨機選擇兩個不相等的質數p和q。

p=61和q=53。(實際應用中,這兩個質數越大,就越難破解。)

2:計算p和q的乘積n。

n = 61×53 = 3233

n的長度就是密鑰長度。3233寫成二進制是110010100001,一共有12位,所以這個密鑰就是12位。實際應用中,RSA密鑰一般是1024位,重要場合則為2048位。

第三步,計算n的歐拉函數φ(n)。

φ(n) = (p-1)(q-1)

φ(3233)等於60×52,即3120。

第四步,隨機選擇一個整數e,條件是1< e < φ(n),且e與φ(n) 互質。

e=17

第五步,計算e對於φ(n)的模反元素d。

ed - 1 = kφ(n)

d=2753。

第六步,將n和e封裝成公鑰,n和d封裝成私鑰。

 

二:理論知識:

1:  模反元素:

如果兩個正整數a和n互質,那么一定可以找到整數b,使得( a乘以b)-1 被n整除,或者說ab被n除的余數是1。 

(a乘以b)-1 = kn.

2: 歐拉函數:計算φ(n)。

任意給定正整數n,請問在小於等於n的正整數之中,有多少個與n構成互質關系?(比如,在1到8之中,有多少個數與8構成互質關系?)計算這個值的方法就叫做歐拉函數,以φ(n)表示。

2.1:n是質數的某一個次方,即 n = p^k (p為質數,k為大於等於1的整數),

則φ(n) = φ(p^k) = p^k - p^(k-1)。也就是φ(8) = φ(2^3) =2^3 - 2^2 = 8 -4 = 4

2.2:如果n是質數,則 φ(n)=n-1 。

計算7的歐拉函數,和7互質的 1、2、3、4、5、6、7
φ(7) = 6

2.3:如果n可以分解成兩個互質的整數之積,即 n = p * k ,則φ(n) = φ(p * k) = φ(p)*φ(k).

φ(56) = φ(8) * φ(7) = 4 * 6 = 24

3:歐拉定理:

如果兩個正整數m和n互質,那么m的φ(n)次方減去1,可以被n整除。

 

4:迪菲赫爾曼秘鑰交換

5:加密解密

m<n.

三:使用rsa加密解密,簽名,認證

1:生成RSA私鑰,base64編碼的二進制數據。

openssl genrsa -out private.pem 1024

生成一個1024位的私鑰

 

2:private.pem 私鑰中提取公鑰,輸出

openssl rsa -in private.pem -pubout -out public.pem

 

 3:查看文件內容

cat private.pem

cat public.pem

pem文件中都是base64編碼的二進制數據。

 

4:將私鑰轉化成明文

將私鑰轉化成明文

openssl rsa -in private.pem -text -out private.txt

 

5:  通過公鑰rsa加密message.txt

openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out enc.txt

 

6:通過私鑰解密enc.txt

openssl rsautl -decrypt -in  enc.txt -inkey private.pem -out dec.txt

 

7:使用私鑰簽名

openssl rsautl -sign -in message.txt  -inkey private.pem -out enc.bin

 

8:xxd查看二進制文件,

 

9:使用公鑰認證

openssl rsautl -verify -in enc.bin -inkey public.pem -pubin -out decode.txt

 

四:使用openssl生成證書

1:從代碼中不會使用直接使用pem,會從pem中提取證書。 需要輸入一些證書請求信息,參考提示內容。

 

 

 

openssl req -new -key private.pem -out rsacert.csr

csr文件不是證書,是請求證書文件。

 

2: 給請求文件 從 pem文件中 提取證書,.crt 這個證書還是base64編碼的,這個crt文件也不是直接使用的。

簽名一個證書一年5千元。

openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt

 

3:生成der文件.  這個der文件主要包含公鑰。最后通過這個來生成一個p12是這個der對應的私鑰文件。

openssl x509 -outform der -in rsacert.crt -out rsacert.der

 

4:通過crt文件通提取私鑰P12文件,公鑰也是從crt中提取出來的

openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt

5:證書的關系

1:der  文件是公鑰

.p12 是私鑰文件

這兩個是二進制文件

 

2:他們是從crt文件中提取出來的,crt文件是從pem文件中提取出來的。

crt和pem中有公鑰和私鑰他們是base64編碼的文件。

 

五:base64編解碼,所有的base64都是對二進制數據操作的。

A-Z   26個大寫

a-z 26個小寫

0-9  10個字母

/ +  =(不足6位的用等號補充) 

等號只會出現在最后面,

對於二進制數據不便於查看或者表示,所以用base64來編碼查看。

 

1:base64編碼

base64 zk.png -o zk.txt

 

2:base64解碼

base64 zk.txt -o zk.png -D

 

六:rsa加密的代碼

rsa加密的是二進制數據。

1:加密

rsa加密的是二進制數據

加密后的數據用base64來表示。表示結果是字符串。

 

2:解密

 解密的是二進制數據。

 

3:填充模式

不填充

pkcs 填充模式,加密數據是隨機的。

 

代碼

1:RSA加密代碼

#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
View Code
#import "RSACryptor.h"

// 填充模式
#define kTypeOfWrapPadding        kSecPaddingPKCS1

// 公鑰/私鑰標簽
#define kPublicKeyTag            "com.zk.publickey"
#define kPrivateKeyTag            "com.zk.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 = NULL;
    SecTrustRef myTrust = NULL;
    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
View Code

 使用

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //1.加載公鑰
    [[RSACryptor sharedRSACryptor] loadPublicKey:[[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil]];
    //2.加載私鑰
    [[RSACryptor sharedRSACryptor] loadPrivateKey: [[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil] password:@"123456"];
    
    
}

static void my_encrypt(){
    NSData * result = [[RSACryptor sharedRSACryptor] encryptData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding]];
    //base64編碼
    NSString * base64 = [result base64EncodedStringWithOptions:0];
    NSLog(@"加密之后:%@\n",base64);
    
    //解密
    NSData * dcStr = [[RSACryptor sharedRSACryptor] decryptData:result];
    NSLog(@"%@",[[NSString alloc] initWithData:dcStr encoding:NSUTF8StringEncoding]);
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    my_encrypt();
}
View Code

 

七:base64代碼、

base64編碼(對二進制數據進行base64編碼)

這個是ios7之后出現的。

//  對一個二進制數據進行編碼,文件會變大! 原有文件的4/3 , 多了1/3
//  不便於查看的二進制數據,用base64進行表示。

//給一個字符 編碼
-(NSString *)base64Endcode:(NSString *)str{
   NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding];
    // 對二進制數據進行base64編碼
    return [data base64EncodedStringWithOptions:0];
}


//給一個編碼我對其進行解密
-(NSString *)base64Decode:(NSString *)str{
    NSData * data = [[NSData alloc] initWithBase64EncodedString:str options:0];
    // 對已經編碼的二進制數據進行解碼
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"%@",[self base64Endcode:@"A"]);
    
    NSLog(@"解碼%@",[self base64Decode:@"QQ=="]);
}
View Code

注意:

RSA算法就要求加密的明文長度不能超過RSA密鑰的長度減去11byte。是自身算法的原因限制的。

說具體點呢,是因為要填充(padding)。RSA實際可加密的明文長度最大其實是1024bits,因為RSA首先就限制了0<明文長度<密鑰長度,但問題就來了:

如果小於這個長度怎么辦?如果不填充,用戶無法確定解密后內容的真實長度,字符串之類的內容問題還不大,以0作為結束符,但對二進制數據就很難理解,因為不確定后面的0是內容還是內容結束符。

只要用到padding,那么就要占用實際的明文長度,於是才有117字節的說法。我們一般使用的padding標准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建議的padding就占用了11個字節。

如果大於這個長度怎么辦?很多算法的padding往往是在后邊的,但PKCS的padding則是在前面的,此為有意設計,有意的把第一個字節置0以確保明文長度小於密鑰長度。

這樣,128字節(1024bits)-減去11字節正好是117字節,但對於RSA加密來講,padding也是參與加密的,所以,依然按照1024bits去理解,但實際的明文只有117字節了。

 

EB=0x00+BT+PS+0x00+(明文) = 128字節

BT在私鑰加密時取0x01,公鑰加密取0x02。

PS在私鑰加密時取0xFF,公鑰加密時取隨機值。PS至少要有八個字節長。

 

Security框架提供的RSA在iOS上使用的一些小結

  • 支持的RSA keySize 大小有:512,768,1024,2048位
  • 支持的RSA 填充方式有三種:NOPadding,PKCS1,OAEP 三種方式 ,填充方式影響最大分組加密數據塊的大小
  • 簽名使用的填充方式PKCS1, 支持的簽名算法有 sha1,sha256,sha224,sha384,sha512
  • Nopadding填充最大數據塊為 下面接口 SecKeyGetBlockSize 大小; 
  • PKCS1 填充方式最大數據為 SecKeyGetBlockSize大小 減去11
  • OAEP 填充方式最大數據為 SecKeyGetBlockSize 大小減去 42
  • RSA加密解密簽名,適合小塊的數據處理,大量數量需要處理分組邏輯;密碼學中推薦使用對稱加密進行數據加密,使用RSA來加密對稱密鑰
  • iOS10,以及mac 10.12中新增加了幾個接口,以下測試用的是老接口,支持iOS2.0

 

備注:

國密

sm2、sm3、sm4

rsa秘鑰原理-阮一峰

rsa加密流程

iOS使用Security.framework進行RSA 加密解密簽名和驗證簽名


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM