RSA加密解密

和后台弄人脸识别这一块时真是欲仙欲死。NND,一直想记录一下,以免以后再掉坑里,拖了个把月才写,真是拖延症加懒癌晚期。网上找的找了很久只有加密,没解密,自己写了个解密。废话不多说了,上代码和解释:其实自己还是不太懂,仿照加密啊写的解密。有错误的话多多欢迎来打脸

。h文件

#import <Foundation/Foundation.h>

@interface W3r_RSA : NSObject
{
    SecKeyRef publicKey;
    SecKeyRef server_privateKey; //服务器私钥
    SecKeyRef myself_privateKey;//自己私钥,签名

    SecCertificateRef certificate;
    SecPolicyRef Public_certificate;

    SecPolicyRef policy;
    SecTrustRef trust;
    size_t maxPlainLen;
}
+(instancetype)sharedManager;

- (NSData *) encryptWithData:(NSData *)content;
- (NSData *) encryptWithString:(NSString *)content;
- (NSString *) encryptToString:(NSString *)content;
#pragma mark 
- (NSString *)DecryptToString:(NSString *)content;
-(NSString *)signTheDataSHA1WithRSA:(NSString *)plainText;

@e

。m文件

//
//  RSA.m
//  Shsm
//
//  Created by lihui on 15/10/28.
//
//

#import "W3r_RSA.h"
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import <Security/Security.h>
#import "NSData+Base64.h"
#import "Base64.h"
#define kChosenDigestLength CC_SHA1_DIGEST_LENGTH  // SHA-1消息摘要的数据位数160位

@implementation W3r_RSA

+(instancetype)sharedManager{
    static W3r_RSA *_sharedManager = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _sharedManager = [[self alloc] init];
    });

    return _sharedManager;
}
- (id)init {
    self = [super init];
//公钥
    NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"server_public_key"
                                                              ofType:@"der"];
    if (publicKeyPath == nil) {
        NSLog(@"Can not find pub.der");
        return nil;
    }
    NSDate *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath];
    if (publicKeyFileContent == nil) {
        NSLog(@"Can not read from pub.der");
        return nil;
    }
    certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent);
    if (certificate == nil) {
        NSLog(@"Can not read certificate from pub.der");
        return nil;
    }
    policy = SecPolicyCreateBasicX509();
    OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust);
    if (returnCode != 0) {
        NSLog(@"SecTrustCreateWithCertificates fail. Error Code: %ld", returnCode);
        return nil;
    }

    SecTrustResultType trustResultType;
    returnCode = SecTrustEvaluate(trust, &trustResultType);
    if (returnCode != 0) {
        return nil;
    }

    publicKey = SecTrustCopyPublicKey(trust);
    if (publicKey == nil) {
        NSLog(@"SecTrustCopyPublicKey fail");
        return nil;
    }
    maxPlainLen = SecKeyGetBlockSize(publicKey) - 12;

    //服务器私钥解密
    NSString *server_privateKeyPath = [[NSBundle mainBundle] pathForResource:@"server_private_key"
                                                              ofType:@"p12"];
    NSData *p12Data=[NSData dataWithContentsOfFile:server_privateKeyPath];
    NSMutableDictionary *server_option=[[NSMutableDictionary alloc] init];
    SecKeyRef server_privateKeyRef =NULL;
    //change to the actual password you usedd here
    [server_option setObject:@"" forKey:(id)kSecImportExportPassphrase];
    CFArrayRef server_items=CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus server_securityError=SecPKCS12Import((CFDataRef)p12Data, (CFDictionaryRef)server_option, &server_items);
    if (server_securityError==noErr&&CFArrayGetCount(server_items)>0) {
        CFDictionaryRef identityDict =CFArrayGetValueAtIndex(server_items, 0);
        SecIdentityRef identityApp=(SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
        server_securityError=SecIdentityCopyPrivateKey(identityApp, &server_privateKeyRef);
        if (server_securityError !=noErr) {
            server_privateKeyRef=NULL;
        }
    }
    CFRelease(server_items);
    server_privateKey=server_privateKeyRef;
    //自己私钥,签名
    NSString *myself_privateKeyPath = [[NSBundle mainBundle] pathForResource:@"private_key"
                                                               ofType:@"p12"];
    NSData *myself_pemData=[NSData dataWithContentsOfFile:myself_privateKeyPath];
    NSMutableDictionary *myself_option=[[NSMutableDictionary alloc] init];
    SecKeyRef myself_privateKeyRef =NULL;
    //change to the actual password you usedd here
    [myself_option setObject:@"" forKey:(id)kSecImportExportPassphrase];
    CFArrayRef items=CFArrayCreate(NULL, 0, 0, NULL);

    OSStatus securityError=SecPKCS12Import((CFDataRef)myself_pemData, (CFDictionaryRef)myself_option, &items);
    if (securityError==noErr&&CFArrayGetCount(items)>0) {
        CFDictionaryRef identityDict =CFArrayGetValueAtIndex(items, 0);
        SecIdentityRef identityApp=(SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
        securityError=SecIdentityCopyPrivateKey(identityApp, &myself_privateKeyRef);
        if (securityError !=noErr) {
            myself_privateKeyRef=NULL;
        }
    }
    CFRelease(items);
    myself_privateKey=myself_privateKeyRef;

    return self;
}

- (NSData *)encryptWithData:(NSData *)content {

    size_t plainLen = [content length];
    if (plainLen > maxPlainLen) {
        NSLog(@"content(%ld) is too long, must < %ld", plainLen, maxPlainLen);
        return nil;
    }

    void *plain = malloc(plainLen);
    [content getBytes:plain
               length:plainLen];

    size_t cipherLen = 128; // currently RSA key length is set to 128 bytes
    void *cipher = malloc(cipherLen);

    OSStatus returnCode = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plain,
                                        plainLen, cipher, &cipherLen);


    NSData *result = nil;
    if (returnCode != 0) {
        NSLog(@"SecKeyEncrypt fail. Error Code: %ld", returnCode);
    }
    else {
        result = [NSData dataWithBytes:cipher
                                length:cipherLen];
    }

    free(plain);
    free(cipher);

    return result;
}

- (NSData *) encryptWithString:(NSString *)content {
    return [self encryptWithData:[content dataUsingEncoding:NSUTF8StringEncoding]];
}

- (NSString *)encryptToString:(NSString *)content {
    NSData *data = [self encryptWithString:content];
    return [self base64forData:data];
}

// convert NSData to NSString
- (NSString*)base64forData:(NSData*)theData {
    const uint8_t* input = (const uint8_t*)[theData bytes];
    NSInteger length = [theData length];

    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t* output = (uint8_t*)data.mutableBytes;

    NSInteger i;
    for (i=0; i < length; i += 3) {
        NSInteger value = 0;
        NSInteger j;
        for (j = i; j < (i + 3); j++) {
            value <<= 8;

            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }

        NSInteger theIndex = (i / 3) * 4;
        output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
        output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
        output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
    }

    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
#pragma mark 解密
- (NSString *)DecryptToString:(NSString *)content {
    NSData *data = [self DecryptWithString:content];
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
- (NSData *)DecryptWithString:(NSString *)content {
  //  return [self DecryptWithData:[Base64 decodeString:content]];
   return [self decryptWithPrivateKey:[Base64 decodeString:content]];
}
- (NSData *)DecryptWithData:(NSData *)content {
    size_t plainLen = [content length];
    void *plain = malloc(plainLen);
    [content getBytes:plain
               length:plainLen];
    size_t cipherLen = SecKeyGetBlockSize(server_privateKey)-12; // currently RSA key length is set to 128 bytes
    void *cipher = malloc(cipherLen);

    OSStatus returnCode =SecKeyDecrypt(server_privateKey, kSecPaddingPKCS1, plain, plainLen, cipher, &cipherLen);
    NSData *result = nil;
    if (returnCode != 0) {
        NSLog(@"SecKeyDecrypt fail. Error Code: %ld", returnCode);
    }
    else {
        result = [NSData dataWithBytes:cipher
                                length:cipherLen];
    }
    free(plain);
    free(cipher);
    return result;
}
- (NSData *)decryptWithPrivateKey:(NSData *)cipherData {
    // 分配内存块,用于存放解密后的数据段
    size_t plainBufferSize = SecKeyGetBlockSize(server_privateKey);
    NSLog(@"plainBufferSize = %zd", plainBufferSize);
    uint8_t *plainBuffer = malloc(plainBufferSize * sizeof(uint8_t));
    // 计算数据段最大长度及数据段的个数
    double totalLength = [cipherData length];
    size_t blockSize = plainBufferSize;
    size_t blockCount = (size_t)ceil(totalLength / blockSize);
    NSMutableData *decryptedData = [NSMutableData data];
    // 分段解密
    for (int i = 0; i < blockCount; i++) {
        NSUInteger loc = i * blockSize;
        // 数据段的实际大小。最后一段可能比blockSize小。
        int dataSegmentRealSize = MIN(blockSize, totalLength - loc);
        // 截取需要解密的数据段
        NSData *dataSegment = [cipherData subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
        OSStatus status = SecKeyDecrypt(server_privateKey, kSecPaddingPKCS1, (const uint8_t *)[dataSegment bytes], dataSegmentRealSize, plainBuffer, &plainBufferSize);
        if (status == errSecSuccess) {
            NSData *decryptedDataSegment = [[NSData alloc] initWithBytes:(const void *)plainBuffer length:plainBufferSize];
            [decryptedData appendData:decryptedDataSegment];
        } else {
            if (plainBuffer) {
                free(plainBuffer);
            }
            return nil;
        }
    }
    if (plainBuffer) {
        free(plainBuffer);
    }
    return decryptedData;
}
//签名
- (NSData *)getHashBytes:(NSData *)plainText {
    CC_SHA1_CTX ctx;
    uint8_t * hashBytes = NULL;
    NSData * hash = nil;

    // Malloc a buffer to hold hash.
    hashBytes = malloc( kChosenDigestLength * sizeof(uint8_t) );
    memset((void *)hashBytes, 0x0, kChosenDigestLength);
    // Initialize the context.
    CC_SHA1_Init(&ctx);
    // Perform the hash.
    CC_SHA1_Update(&ctx, (void *)[plainText bytes], [plainText length]);
    // Finalize the output.
    CC_SHA1_Final(hashBytes, &ctx);

    // Build up the SHA1 blob.
    hash = [NSData dataWithBytes:(const void *)hashBytes length:(NSUInteger)kChosenDigestLength];
    if (hashBytes) free(hashBytes);

    return hash;
}




-(NSString *)signTheDataSHA1WithRSA:(NSString *)plainText
{
    uint8_t* signedBytes = NULL;
    size_t signedBytesSize = 0;
    OSStatus sanityCheck = noErr;
    NSData* signedHash = nil;

    NSString * path = [[NSBundle mainBundle]pathForResource:@"private_key" ofType:@"p12"];
    NSData * data = [NSData dataWithContentsOfFile:path];
    NSMutableDictionary * options = [[NSMutableDictionary alloc] init]; // Set the private key query dictionary.
    [options setObject:@"" forKey:(id)kSecImportExportPassphrase];
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import((CFDataRef) data, (CFDictionaryRef)options, &items);
    if (securityError!=noErr) {
        return nil ;
    }
    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
    SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);
    SecKeyRef privateKeyRef=nil;
    SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
    signedBytesSize = SecKeyGetBlockSize(privateKeyRef);

    NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];

    signedBytes = malloc( signedBytesSize * sizeof(uint8_t) ); // Malloc a buffer to hold signature.
    memset((void *)signedBytes, 0x0, signedBytesSize);

    sanityCheck = SecKeyRawSign(privateKeyRef,
                                kSecPaddingPKCS1SHA1,
                                (const uint8_t *)[[self getHashBytes:plainTextBytes] bytes],
                                kChosenDigestLength,
                                (uint8_t *)signedBytes,
                                &signedBytesSize);

    if (sanityCheck == noErr)
    {
        signedHash = [NSData dataWithBytes:(const void *)signedBytes length:(NSUInteger)signedBytesSize];
    }
    else
    {
        return nil;
    }

    if (signedBytes)
    {
        free(signedBytes);
    }
    NSString *signatureResult=[NSString stringWithFormat:@"%@",[signedHash base64EncodedString]];
    return signatureResult;
}


- (void)dealloc{
    CFRelease(certificate);
    CFRelease(trust);
    CFRelease(policy);
    CFRelease(publicKey);
}

@end

用的时候直接 调用

pragma mark

  • (NSString )DecryptToString:(NSString )content;
    -(NSString )signTheDataSHA1WithRSA:(NSString )plainText;
    这两个方法就行了。
    当然了,公钥,私钥要换成自己的。注意文件类型。别怕烦,不然你会更烦。。
    里面有签名,不需要可以注释了。

懒人可以直接下载,我把这俩文件上传。不过要2分。。谁让你懒呢。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值