你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS AES256/RSA/MD5/sha-1 (加密/解密)

iOS AES256/RSA/MD5/sha-1 (加密/解密)

編輯:IOS開發綜合

分享源碼,讓苦逼的開發生活見鬼去。

最近一直苦於開發,今天稍微有些時間,趁機先分享一下數據的加解密。後續補充用戶數據的加密存儲以及數據存儲管理。

1.AES加密(對稱加密)

特點:

優點:簡單、可並行計算、誤差不傳遞

缺點:不能隱藏明文模式(比如圖像加密輪廓仍在)、主動攻擊(改明文,後續內容不影響,只要誤差不傳遞該缺點就存在)

用途:需要並行加密的應用

AES加密算法是密碼學中的高級加密標准,該加密算法采用對稱分組密碼體制,密鑰長度的最少支持為128、192、256,分組長度128位,算法應易於各種硬件和軟件實現。這種加密算法是美國聯邦政府采用的區塊加密標准,這個標准用來替代原先的DES,已經被多方分析且廣為全世界所使用。設計為支持128/192/256位(/32=nb)數據塊大小(即分組長度);支持128/192/256位(/32=nk)密碼長度,,在10進制裡,對應34×1038、62×1057、1.1×1077個密鑰

AES加密的原理可以百度,這裡就不詳細說明了,下面進入開發正題

NSData+AES.m 文件

 

//
//  NSData+AES.m
//  Encryption
//
//  Created by llyouss on 16/10/16.
//  Copyright © 2016年 llyouss. All rights reserved.
//

#import "NSData+AES.h"
#import 
@implementation NSData (AES)

- (NSData *)AES256EncryptWithKey:(NSString *)key {//加密
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr, kCCBlockSizeAES128,
                                          NULL,
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return nil;
}


- (NSData *)AES256DecryptWithKey:(NSString *)key {//解密
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr, kCCBlockSizeAES128,
                                          NULL,
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }
    free(buffer);
    return nil;
}

#import 
@end

由於字符集沖突,我們先nsdata或base64位編碼的形式存下來,否則會出現亂碼。

調用事例

導入#import "SecurityUtil.h"

 

-(void)AESEncryption{
    NSString *testString = @"AESllyouss";
    NSLog(@"BASE64:%@", [SecurityUtil encodeBase64String:testString]);
    NSLog(@"MD5:%@", [SecurityUtil encryptMD5String:testString]);
    
    NSData *aesData = [SecurityUtil encryptAESData:testString];
    NSLog(@"AES加密:%@", aesData);
    NSLog(@"AES解密:%@", [SecurityUtil decryptAESData:aesData]);

}

2.BASE64編碼

其實base64編解碼方式使用系統的api已經很方便,但是還是喜歡現成的。

下載GTMBase64文件,在工程中加入三個文件
GTMDefines.h
GTMBase64.h
GTMBase64.m
下載地址:點擊打開鏈接

封裝一下

 

//
//  SecurityUtil.m
//  Encryption
//
//  Created by llyouss on 16/10/16.
//  Copyright © 2016年 llyouss. All rights reserved.
//

#import "SecurityUtil.h"
#import "GTMBase64.h"
#import "NSData+AES.h"
#import "NSString+MD5.h"

#define APP_PUBLIC_PASSWORD     @"boundary"
@implementation SecurityUtil

#pragma mark - base64
+ (NSString*)encodeBase64String:(NSString * )input {
    NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    data = [GTMBase64 encodeData:data];
    NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ;
    return base64String;
}

+ (NSString*)decodeBase64String:(NSString * )input {
    NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    data = [GTMBase64 decodeData:data];
    NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return base64String;
}

+ (NSString*)encodeBase64Data:(NSData *)data {
    data = [GTMBase64 encodeData:data];
    NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return base64String;
}

+ (NSString*)decodeBase64Data:(NSData *)data {
    data = [GTMBase64 decodeData:data];
    NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return base64String;
}
   

3.MD5

MD5是哈希算法,作用大家都應該知道,加密非常簡單直接上方法

- (NSString *)md5Encrypt {
    
    const char *cStr = [self UTF8String];
    unsigned char result[16];
    CC_MD5( cStr, (int)strlen(cStr), result );
    NSMutableString *hash = [NSMutableString string];
    for (int i = 0; i < 16; i++)
        [hash appendFormat:@"%02X", result[i]];
    return [hash lowercaseString];
}

4.sha1&sha256加密

MD5目前發現了重復,目前最新的是sha256,具體作用大家都應該知道。

 

 

//sha256加密方式
- (NSString *)Sha256String:(NSString *)srcString {
    const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:srcString.length];

    uint8_t digest[CC_SHA256_DIGEST_LENGTH];

    CC_SHA256(data.bytes, data.length, digest);

    NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];

    for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
        [result appendFormat:@"%02x", digest[i]];
    }

    return result;
}
- (NSString *)sha1Encrypt{
    
    const char *cstr = [self UTF8String];
    NSData *data = [NSData dataWithBytes:cstr length:self.length];
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
    
    CC_SHA1(data.bytes, (int)data.length, digest);
    
    NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
    
    for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
        [output appendFormat:@"%02x", digest[i]];
    return output;
}


5.RSA加密(非對稱加密)

特點

RSA加密算法是目前最有影響力的公鑰加密算法,並且被普遍認為是目前最優秀的公鑰方案之一。RSA是第一個能同時用於加密和數宇簽名的算法,它能夠抵抗到目前為止已知的所有密碼攻擊,已被ISO推薦為公鑰數據加密標准。RSA加密算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰。

 

使用openssl實現,可以在這下載:點擊打開鏈接

1.生成RSA密鑰
* 生成RSA私鑰
openssl genrsa -out rsa_private_key.pem 1024
* 生成RSA公鑰
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
pem文件可以直接文本編輯器打開
將RSA私鑰轉換成PKCS8格式
openssl pkcs8 -topk8 -inform PEM -in private_rsa.pem -outform PEM -nocrypt -out private_key.pem (後邊一定要加-out private_key.pem將轉換後的私鑰保存在private_key.pem,不然得到的結果要設置密碼且顯示在終端中,這個和得到pem中的私鑰有差異。)

2.導入OpenSSL,導入HBRSAHandler褲文件
小技巧:記得在headSearchpath設置路徑,不然編譯報錯。

HBRSAHandler.m 文件

 

//
//  HBRSAHandler.m
//  iOSRSAHandlerDemo
//
//  Created by wangfeng on 15/10/19.
//  Copyright (c) 2015年 HustBroventure. All rights reserved.
//
#import "HBRSAHandler.h"
#include 
#include 
#include 
#include 

typedef enum {
    RSA_PADDING_TYPE_NONE       = RSA_NO_PADDING,
    RSA_PADDING_TYPE_PKCS1      = RSA_PKCS1_PADDING,
    RSA_PADDING_TYPE_SSLV23     = RSA_SSLV23_PADDING
}RSA_PADDING_TYPE;

#define  PADDING   RSA_PADDING_TYPE_PKCS1

@implementation HBRSAHandler
{

    RSA* _rsa_pub;
    RSA* _rsa_pri;
}
#pragma mark - public methord
-(BOOL)importKeyWithType:(KeyType)type andPath:(NSString *)path
{
    BOOL status = NO;
    const char* cPath = [path cStringUsingEncoding:NSUTF8StringEncoding];
    FILE* file = fopen(cPath, "rb");
    if (!file) {
        return status;
    }
    if (type == KeyTypePublic) {
        _rsa_pub = NULL;
        if((_rsa_pub = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL))){
            status = YES;
        }
        
        
    }else if(type == KeyTypePrivate){
        _rsa_pri = NULL;
        if ((_rsa_pri = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL))) {
            status = YES;
        }

    }
    fclose(file);
    return status;

}
- (BOOL)importKeyWithType:(KeyType)type andkeyString:(NSString *)keyString
{
    if (!keyString) {
        return NO;
    }
    BOOL status = NO;
    BIO *bio = NULL;
    RSA *rsa = NULL;
    bio = BIO_new(BIO_s_file());
    NSString* temPath = NSTemporaryDirectory();
    NSString* rsaFilePath = [temPath stringByAppendingPathComponent:@"RSAKEY"];
    NSString* formatRSAKeyString = [self formatRSAKeyWithKeyString:keyString andKeytype:type];
    BOOL writeSuccess = [formatRSAKeyString writeToFile:rsaFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    if (!writeSuccess) {
        return NO;
    }
    const char* cPath = [rsaFilePath cStringUsingEncoding:NSUTF8StringEncoding];
    BIO_read_filename(bio, cPath);
    if (type == KeyTypePrivate) {
        rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, "");
        _rsa_pri = rsa;
        if (rsa != NULL && 1 == RSA_check_key(rsa)) {
            status = YES;
        } else {
            status = NO;
        }


    }
    else{
        rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
        _rsa_pub = rsa;
        if (rsa != NULL) {
            status = YES;
        } else {
            status = NO;
        }
    }
    
           BIO_free_all(bio);
    [[NSFileManager defaultManager] removeItemAtPath:rsaFilePath error:nil];
    return status;
}


#pragma mark RSA sha1驗證簽名
    //signString為base64字符串
- (BOOL)verifyString:(NSString *)string withSign:(NSString *)signString
{
    if (!_rsa_pub) {
        NSLog(@"please import public key first");
        return NO;
    }

    const char *message = [string cStringUsingEncoding:NSUTF8StringEncoding];
    int messageLength = (int)[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    NSData *signatureData = [[NSData alloc]initWithBase64EncodedString:signString options:0];
    unsigned char *sig = (unsigned char *)[signatureData bytes];
    unsigned int sig_len = (int)[signatureData length];
    

    
   
    unsigned char sha1[20];
    SHA1((unsigned char *)message, messageLength, sha1);
       int verify_ok = RSA_verify(NID_sha1
                                      , sha1, 20
                                      , sig, sig_len
                                      , _rsa_pub);

    if (1 == verify_ok){
        return   YES;
    }
    return NO;
    
    
}
#pragma mark RSA MD5 驗證簽名
- (BOOL)verifyMD5String:(NSString *)string withSign:(NSString *)signString
{
    if (!_rsa_pub) {
        NSLog(@"please import public key first");
        return NO;
    }

    const char *message = [string cStringUsingEncoding:NSUTF8StringEncoding];
        // int messageLength = (int)[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    NSData *signatureData = [[NSData alloc]initWithBase64EncodedString:signString options:0];
    unsigned char *sig = (unsigned char *)[signatureData bytes];
    unsigned int sig_len = (int)[signatureData length];
    
    unsigned char digest[MD5_DIGEST_LENGTH];
    MD5_CTX ctx;
    MD5_Init(&ctx);
    MD5_Update(&ctx, message, strlen(message));
    MD5_Final(digest, &ctx);
    int verify_ok = RSA_verify(NID_md5
                                      , digest, MD5_DIGEST_LENGTH
                                      , sig, sig_len
                                      , _rsa_pub);
    if (1 == verify_ok){
        return   YES;
    }
    return NO;
    
}

- (NSString *)signString:(NSString *)string
{
    if (!_rsa_pri) {
        NSLog(@"please import private key first");
        return nil;
    }
    const char *message = [string cStringUsingEncoding:NSUTF8StringEncoding];
    int messageLength = (int)strlen(message);
    unsigned char *sig = (unsigned char *)malloc(256);
    unsigned int sig_len;
    
    unsigned char sha1[20];
    SHA1((unsigned char *)message, messageLength, sha1);
    
    int rsa_sign_valid = RSA_sign(NID_sha1
                                          , sha1, 20
                                          , sig, &sig_len
                                          , _rsa_pri);
    if (rsa_sign_valid == 1) {
        NSData* data = [NSData dataWithBytes:sig length:sig_len];
        
        NSString * base64String = [data base64EncodedStringWithOptions:0];
        free(sig);
        return base64String;
    }
    
    free(sig);
    return nil;
}
- (NSString *)signMD5String:(NSString *)string
{
    if (!_rsa_pri) {
        NSLog(@"please import private key first");
        return nil;
    }
    const char *message = [string cStringUsingEncoding:NSUTF8StringEncoding];
        //int messageLength = (int)strlen(message);
    unsigned char *sig = (unsigned char *)malloc(256);
    unsigned int sig_len;
    
    unsigned char digest[MD5_DIGEST_LENGTH];
    MD5_CTX ctx;
    MD5_Init(&ctx);
    MD5_Update(&ctx, message, strlen(message));
    MD5_Final(digest, &ctx);
    
    int rsa_sign_valid = RSA_sign(NID_md5
                                  , digest, MD5_DIGEST_LENGTH
                                  , sig, &sig_len
                                  , _rsa_pri);
   
    if (rsa_sign_valid == 1) {
        NSData* data = [NSData dataWithBytes:sig length:sig_len];
        
        NSString * base64String = [data base64EncodedStringWithOptions:0];
        free(sig);
        return base64String;
    }
    
    free(sig);
    return nil;

    
}

- (NSString *) encryptWithPublicKey:(NSString*)content
{
    if (!_rsa_pub) {
        NSLog(@"please import public key first");
        return nil;
    }
    int status;
    int length  = (int)[content length];
    unsigned char input[length + 1];
    bzero(input, length + 1);
    int i = 0;
    for (; i < length; i++)
        {
        input[i] = [content characterAtIndex:i];
        }
    
    NSInteger  flen = [self getBlockSizeWithRSA_PADDING_TYPE:PADDING andRSA:_rsa_pub];
    
    char *encData = (char*)malloc(flen);
    bzero(encData, flen);
    status = RSA_public_encrypt(length, (unsigned char*)input, (unsigned char*)encData, _rsa_pub, PADDING);
    
    if (status){
        NSData *returnData = [NSData dataWithBytes:encData length:status];
        free(encData);
        encData = NULL;
        
            //NSString *ret = [returnData base64EncodedString];
        NSString *ret = [returnData base64EncodedStringWithOptions: NSDataBase64Encoding64CharacterLineLength];
        return ret;
        }
    
    free(encData);
    encData = NULL;
    
    return nil;
}

- (NSString *) decryptWithPrivatecKey:(NSString*)content
{
    if (!_rsa_pri) {
        NSLog(@"please import private key first");
        return nil;
    }    int status;
    
        //NSData *data = [content base64DecodedData];
    NSData *data = [[NSData alloc]initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];
    int length = (int)[data length];
    
    NSInteger flen = [self getBlockSizeWithRSA_PADDING_TYPE:PADDING andRSA:_rsa_pri];
    char *decData = (char*)malloc(flen);
    bzero(decData, flen);
    
    status = RSA_private_decrypt(length, (unsigned char*)[data bytes], (unsigned char*)decData, _rsa_pri, PADDING);
   
    if (status)
        {
        NSMutableString *decryptString = [[NSMutableString alloc] initWithBytes:decData length:strlen(decData) encoding:NSASCIIStringEncoding];
        free(decData);
        decData = NULL;
        
        return decryptString;
        }
    
    free(decData);
    decData = NULL;
    
    return nil;
}

- (int)getBlockSizeWithRSA_PADDING_TYPE:(RSA_PADDING_TYPE)padding_type andRSA:(RSA*)rsa
{
    int len = RSA_size(rsa);
    
    if (padding_type == RSA_PADDING_TYPE_PKCS1 || padding_type == RSA_PADDING_TYPE_SSLV23) {
        len -= 11;
    }
    
    return len;
}

-(NSString*)formatRSAKeyWithKeyString:(NSString*)keyString andKeytype:(KeyType)type
{
    NSInteger lineNum = -1;
    NSMutableString *result = [NSMutableString string];
    
    if (type == KeyTypePrivate) {
        [result appendString:@"-----BEGIN PRIVATE KEY-----\n"];
        lineNum = 79;
    }else if(type == KeyTypePublic){
    [result appendString:@"-----BEGIN PUBLIC KEY-----\n"];
         lineNum = 76;
    }
   
    int count = 0;
    for (int i = 0; i < [keyString length]; ++i) {
        unichar c = [keyString characterAtIndex:i];
        if (c == '\n' || c == '\r') {
            continue;
        }
        [result appendFormat:@"%c", c];
        if (++count == lineNum) {
            [result appendString:@"\n"];
            count = 0;
        }
    }
    if (type == KeyTypePrivate) {
        [result appendString:@"\n-----END PRIVATE KEY-----"];
       
    }else if(type == KeyTypePublic){
        [result appendString:@"\n-----END PUBLIC KEY-----"];
    }
    return result;
 
}
@end

調用事例

 

導入#import "HBRSAHandler.h"

 

@implementation ViewController
{
    HBRSAHandler* _handler;
    
}
NSString* private_key_string = @"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOn0Mx9WBXbQYr55JsLKHdai1kO/iyA89YqUY3K0PK/YcCqsDNJ8y1VZQ4MBA4er6yr1LR3kSe6z6uux4oP2N4FHuV/BKM/MEkb0oyEKnuOXspOumOZ3Hn/CzpYSZSIAr5BgfADEUU9yfr+nTNIxW5sXh4bZmy3lRsSAKqeinmA9AgMBAAECgYEAxB/va2mVkxEGdl7h25HMic5giNLeMtxnixDyfYoTBecPwPYSmbH8U0RNkFkdOHMq5gw7Ej/6qp0xZvzsw2t5AtFmuAXjt1LS64ofsnbjxgKVYdMsLIn0jFSRt/riyvZLNEpNEwpbGb2Y1M9gCPHmBPU2CMgbKWvkiYquNCIVmoECQQD1wqXLRHY475AL/2AwAIUxGYeVdccL4qsDbsoUZNfaVC5iCvfgzArIg+xX4+XtKnuyuFFrRQWCVbgrsKGSn+6ZAkEA87OfAaKuRmPwMtyd4EY5GBhiOWQinWKIV9PkwozL+wyylHAdfKnMnCzglHFm5hdB+MkHs2R70R+U9DW82Vs5RQJAf+obH0x3+DSAli4Ko5FxwdeW4W0W+BG3jybYGXtPejz8k11AHYo2Rp2bozdkUmgdUC1te1bGgksZe+wIfOevaQJAU838KyrPdYNekY8Od5aOgbu443WM9cRxkIpci46xgsauDp+zdDBMHZTNMh8BPLTYyf4PuOAgOBz9MzHbnH9jZQJBAJKvVlrN3tehLIjBjzK1gfgqzIXDMZM/XkBVz8SIbz5SbeouGKCvGcSjLqD+CCFSdr8fP1EjQ0SiEwfpCpUHBcs=";


NSString* public_key_string = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDp9DMfVgV20GK+eSbCyh3WotZDv4sgPPWKlGNytDyv2HAqrAzSfMtVWUODAQOHq+sq9S0d5Enus+rrseKD9jeBR7lfwSjPzBJG9KMhCp7jl7KTrpjmdx5/ws6WEmUiAK+QYHwAxFFPcn6/p0zSMVubF4eG2Zst5UbEgCqnop5gPQIDAQAB";

 

//RSA加密/簽名
-(void)RSAEncryptionAndDigest{
    HBRSAHandler* handler = [HBRSAHandler new];
    [handler importKeyWithType:KeyTypePrivate andkeyString:private_key_string];
    [handler importKeyWithType:KeyTypePublic andkeyString:public_key_string];
    _handler = handler;
    
    //    加密
    NSString*str=@"RSAllyouss";
    NSData *nsdata = [str dataUsingEncoding:NSUTF8StringEncoding];
    // Get NSString from NSData object in Base64
    NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
    NSString* enString = [handler encryptWithPublicKey:base64Encoded];
    NSLog(@"RSA加密:%@", enString);
    
    //    解密
    NSString* deString = [handler decryptWithPrivatecKey:enString];
    NSData *nsdataFromBase64String = [[NSData alloc]
                                      initWithBase64EncodedString:deString options:0];
    NSLog(@"RSA解密:%@", deString);

    // Decoded NSString from the NSData
    NSString *base64Decoded = [[NSString alloc]
                               initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding];

    NSLog(@"%@",base64Decoded);
    //    MD5簽名
    NSString* sigMd5 = [handler signMD5String:enString];
    NSLog(@"%@ ",sigMd5);
    //   MD5驗簽
    BOOL isMatchMd5 = [handler verifyMD5String:enString withSign:sigMd5];
    NSLog(@"%d ",isMatchMd5);
    
}
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved