注册 登录
主题 : RSA公钥只返回一串base64字符 怎么使用?
级别: 新手上路
UID: 456810
精华: 0
发帖: 32
可可豆: 86 CB
威望: 86 点
在线时间: 127(时)
注册时间: 2015-04-01
最后登录: 2017-12-06
0 楼:  发表于: 2017-10-12 09:59    发自: Web Page
来源于 一般提问 分类

RSA公钥只返回一串base64字符 怎么使用?   

如题,服务器加密机拿到的rsa公钥并非以---begin public key----XXX-----end public key----- 这种格式返回的,而是加密后的base64字符串 请问要怎么使用这个公钥,来进行rsa加密呢。。。
[ 此帖被DanyCocoa在2017-10-12 10:38重新编辑 ]

关键词: RSA公钥 base64
级别: 新手上路
UID: 456810
精华: 0
发帖: 32
可可豆: 86 CB
威望: 86 点
在线时间: 127(时)
注册时间: 2015-04-01
最后登录: 2017-12-06
1 楼:  发表于: 2017-10-12 10:08    发自: Web Page
在线等啊..
级别: 新手上路
UID: 456810
精华: 0
发帖: 32
可可豆: 86 CB
威望: 86 点
在线时间: 127(时)
注册时间: 2015-04-01
最后登录: 2017-12-06
2 楼:  发表于: 2017-10-12 10:16    发自: Web Page
没有人知道吗?
级别: 骑士
状态: 连续签到 - [3天]
UID: 362848
精华: 0
发帖: 328
可可豆: 379 CB
威望: 373 点
在线时间: 495(时)
注册时间: 2014-08-19
最后登录: 2017-12-15
3 楼:  发表于: 2017-10-12 11:03    发自: Web Page
哈哈哈 小伙子很会鼓捣嘛


#import "RSA.h"
#import <Security/Security.h>

@implementation RSA{
    NSRegularExpression *_headerRegex;
    NSRegularExpression *_footerRegex;
}

/*
static NSString *base64_encode(NSString *str){
    NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
    if(!data){
        return nil;
    }
    return base64_encode_data(data);
}
*/

- (instancetype)init
{
    self = [super init];
    if (self) {
        _headerRegex = [NSRegularExpression regularExpressionWithPattern:@"-----BEGIN (RSA )?(PUBLIC|PRIVATE) KEY-----"
                                                                 options:0
                                                                   error:nil];
        _footerRegex = [NSRegularExpression regularExpressionWithPattern:@"-----END (RSA )?(PUBLIC|PRIVATE) KEY-----"
                                                                 options:0
                                                                   error:nil];
    }
    return self;
}

static NSString *base64_encode_data(NSData *data){
    data = [data base64EncodedDataWithOptions:0];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

static NSData *base64_decode(NSString *str){
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    return data;
}

+ (NSData *)stripPublicKeyHeader:(NSData *)d_key{
    // Skip ASN.1 public key header
    if (d_key == nil) return(nil);
    
    unsigned long len = [d_key length];
    if (!len) return(nil);
    
    unsigned char *c_key = (unsigned char *)[d_key bytes];
    unsigned int  idx     = 0;
    
    if (c_key[idx++] != 0x30) return(nil);
    
    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    else idx++;
    
    // PKCS #1 rsaEncryption szOID_RSA_RSA
    static unsigned char seqiod[] =
    { 0x30,   0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
        0x01, 0x05, 0x00 };
    if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
    
    idx += 15;
    
    if (c_key[idx++] != 0x03) return(nil);
    
    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    else idx++;
    
    if (c_key[idx++] != '\0') return(nil);
    
    // Now make a new NSData from this buffer
    return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}

//credit: http://hg.mozilla.org/services/fx-home/file/tip/Sources/NetworkAndStorage/CryptoUtils.m#l1036
+ (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
    // Skip ASN.1 private key header
    if (d_key == nil) return(nil);

    unsigned long len = [d_key length];
    if (!len) return(nil);

    unsigned char *c_key = (unsigned char *)[d_key bytes];
    unsigned int  idx     = 22; //magic byte at offset 22

    if (0x04 != c_key[idx++]) return nil;

    //calculate length of the key
    unsigned int c_len = c_key[idx++];
    int det = c_len & 0x80;
    if (!det) {
        c_len = c_len & 0x7f;
    } else {
        int byteCount = c_len & 0x7f;
        if (byteCount + idx > len) {
            //rsa length field longer than buffer
            return nil;
        }
        unsigned int accum = 0;
        unsigned char *ptr = &c_key[idx];
        idx += byteCount;
        while (byteCount) {
            accum = (accum << 8) + *ptr;
            ptr++;
            byteCount--;
        }
        c_len = accum;
    }

    // Now make a new NSData from this buffer
    return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
}

+ (SecKeyRef)addPublicKey:(NSString *)key{
    NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
    NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        key = [key substringWithRange:range];
    }
    key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];
    
    // This will be base64 encoded, decode it.
    NSData *data = base64_decode(key);
    data = [RSA stripPublicKeyHeader:data];
    if(!data){
        return nil;
    }

    //a tag to read/write keychain storage
    NSString *tag = @"RSAUtil_PubKey";
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
    
    // Delete any old lingering key with the same tag
    NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
    [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
    [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
    SecItemDelete((__bridge CFDictionaryRef)publicKey);
    
    // Add persistent version of the key to system keychain
    [publicKey setObject:data forKey:(__bridge id)kSecValueData];
    [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)
     kSecAttrKeyClass];
    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
     kSecReturnPersistentRef];
    
    CFTypeRef persistKey = nil;
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
    if (persistKey != nil){
        CFRelease(persistKey);
    }
    if ((status != noErr) && (status != errSecDuplicateItem)) {
        return nil;
    }

    [publicKey removeObjectForKey:(__bridge id)kSecValueData];
    [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    
    // Now fetch the SecKeyRef version of the key
    SecKeyRef keyRef = nil;
    status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
    if(status != noErr){
        return nil;
    }
    return keyRef;
}

+ (SecKeyRef)addPrivateKey:(NSString *)key{
    NSRange spos;
    NSRange epos;
    spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
    if(spos.length > 0){
        epos = [key rangeOfString:@"-----END RSA PRIVATE KEY-----"];
    }else{
        spos = [key rangeOfString:@"-----BEGIN PRIVATE KEY-----"];
        epos = [key rangeOfString:@"-----END PRIVATE KEY-----"];
    }
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        key = [key substringWithRange:range];
    }
    key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];

    // This will be base64 encoded, decode it.
    NSData *data = base64_decode(key);
    data = [RSA stripPrivateKeyHeader:data];
    if(!data){
        return nil;
    }

    //a tag to read/write keychain storage
    NSString *tag = @"RSAUtil_PrivKey";
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];

    // Delete any old lingering key with the same tag
    NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
    [privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
    [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
    SecItemDelete((__bridge CFDictionaryRef)privateKey);

    // Add persistent version of the key to system keychain
    [privateKey setObject:data forKey:(__bridge id)kSecValueData];
    [privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
     kSecAttrKeyClass];
    [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
     kSecReturnPersistentRef];

    CFTypeRef persistKey = nil;
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
    if (persistKey != nil){
        CFRelease(persistKey);
    }
    if ((status != noErr) && (status != errSecDuplicateItem)) {
        return nil;
    }

    [privateKey removeObjectForKey:(__bridge id)kSecValueData];
    [privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
    [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

    // Now fetch the SecKeyRef version of the key
    SecKeyRef keyRef = nil;
    status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
    if(status != noErr){
        return nil;
    }
    return keyRef;
}

/* START: Encryption & Decryption with RSA private key */

+ (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
    const uint8_t *srcbuf = (const uint8_t *)[data bytes];
    size_t srclen = (size_t)data.length;
    
    size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
    void *outbuf = malloc(block_size);
    size_t src_block_size = block_size - 11;
    
    NSMutableData *ret = [[NSMutableData alloc] init];
    for(int idx=0; idx<srclen; idx+=src_block_size){
        //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
        size_t data_len = srclen - idx;
        if(data_len > src_block_size){
            data_len = src_block_size;
        }
        
        size_t outlen = block_size;
        OSStatus status = noErr;
        status = SecKeyEncrypt(keyRef,
                               kSecPaddingPKCS1,
                               srcbuf + idx,
                               data_len,
                               outbuf,
                               &outlen
                               );
        if (status != 0) {
            NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
            ret = nil;
            break;
        }else{
            [ret appendBytes:outbuf length:outlen];
        }
    }
    
    free(outbuf);
    CFRelease(keyRef);
    return ret;
}

+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey{
    NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] privateKey:privKey];
    NSString *ret = base64_encode_data(data);
    return ret;
}

+ (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey{
    if(!data || !privKey){
        return nil;
    }
    SecKeyRef keyRef = [RSA addPrivateKey:privKey];
    if(!keyRef){
        return nil;
    }
    return [RSA encryptData:data withKeyRef:keyRef];
}

+ (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
    const uint8_t *srcbuf = (const uint8_t *)[data bytes];
    size_t srclen = (size_t)data.length;
    
    size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
    UInt8 *outbuf = malloc(block_size);
    size_t src_block_size = block_size;
    
    NSMutableData *ret = [[NSMutableData alloc] init];
    for(int idx=0; idx<srclen; idx+=src_block_size){
        //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
        size_t data_len = srclen - idx;
        if(data_len > src_block_size){
            data_len = src_block_size;
        }
        
        size_t outlen = block_size;
        OSStatus status = noErr;
        status = SecKeyDecrypt(keyRef,
                               kSecPaddingNone,
                               srcbuf + idx,
                               data_len,
                               outbuf,
                               &outlen
                               );
        if (status != 0) {
            NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
            ret = nil;
            break;
        }else{
            //the actual decrypted data is in the middle, locate it!
            int idxFirstZero = -1;
            int idxNextZero = (int)outlen;
            for ( int i = 0; i < outlen; i++ ) {
                if ( outbuf == 0 ) {
                    if ( idxFirstZero < 0 ) {
                        idxFirstZero = i;
                    } else {
                        idxNextZero = i;
                        break;
                    }
                }
            }
            
            [ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];
        }
    }
    
    free(outbuf);
    CFRelease(keyRef);
    return ret;
}


+ (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    data = [RSA decryptData:data privateKey:privKey];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

+ (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{
    if(!data || !privKey){
        return nil;
    }
    SecKeyRef keyRef = [RSA addPrivateKey:privKey];
    if(!keyRef){
        return nil;
    }
    return [RSA decryptData:data withKeyRef:keyRef];
}

/* END: Encryption & Decryption with RSA private key */

/* START: Encryption & Decryption with RSA public key */

+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{
    NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
    NSString *ret = base64_encode_data(data);
    return ret;
}

+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
    if(!data || !pubKey){
        return nil;
    }
    SecKeyRef keyRef = [RSA addPublicKey:pubKey];
    if(!keyRef){
        return nil;
    }
    return [RSA encryptData:data withKeyRef:keyRef];
}

+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey{
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    data = [RSA decryptData:data publicKey:pubKey];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey{
    if(!data || !pubKey){
        return nil;
    }
    SecKeyRef keyRef = [RSA addPublicKey:pubKey];
    if(!keyRef){
        return nil;
    }
    return [RSA decryptData:data withKeyRef:keyRef];
}

/* END: Encryption & Decryption with RSA public key */

- (BOOL)verifyHeader:(NSString *)header footer:(NSString *)footer inKey:(NSString *)pemKey {
    NSTextCheckingResult *headerMatch = [_headerRegex firstMatchInString:pemKey
                                                                 options:0
                                                                   range:NSMakeRange(0, pemKey.length)];
    NSTextCheckingResult *footerMatch = [_footerRegex firstMatchInString:pemKey
                                                                 options:0
                                                                   range:NSMakeRange(0, pemKey.length)];
    if (!headerMatch && !footerMatch) {
        // Input key doesn't have a header or footer, this is okay
        return YES;
    } else if (!headerMatch || !footerMatch) {
        // Missing header xor footer
        return NO;
    }
    if (![[pemKey substringWithRange:headerMatch.range] isEqualToString:header]) {
        return NO;
    }
    if (![[pemKey substringWithRange:footerMatch.range] isEqualToString:footer]) {
        return NO;
    }
    return YES;
}

- (NSString *)loadX509PEMPublicKey:(NSString *)pemKey {
    if (![self verifyHeader:@"-----BEGIN PUBLIC KEY-----"
                     footer:@"-----END PUBLIC KEY-----"
                      inKey:pemKey]) {
        return nil;
    }
    NSString *keyData = [self extractKeyData:pemKey];
    if (keyData == nil) {
        return nil;
    }
    return keyData;
}

- (NSString *)extractKeyData:(NSString *)pemKey {
    NSString *stripped = [self strippedPEMKey:pemKey];
    return stripped;
}

- (NSString *)strippedPEMKey:(NSString *)pemKey {
    NSMutableString *stripped = [NSMutableString stringWithString:pemKey];
    [_headerRegex replaceMatchesInString:stripped
                                 options:0
                                   range:NSMakeRange(0, stripped.length)
                            withTemplate:@""];
    [_footerRegex replaceMatchesInString:stripped
                                 options:0
                                   range:NSMakeRange(0, stripped.length)
                            withTemplate:@""];
    [stripped replaceOccurrencesOfString:@"\n"
                              withString:@""
                                 options:0
                                   range:NSMakeRange(0, stripped.length)];
    return stripped;
}

- (NSString *)loadRSAPEMPrivateKey:(NSString *)pemKey {
    if (![self verifyHeader:@"-----BEGIN RSA PRIVATE KEY-----"
                     footer:@"-----END RSA PRIVATE KEY-----"
                      inKey:pemKey]) {
        return nil;
    }
    NSString *keyData = [self extractKeyData:pemKey];
    if (keyData == nil) {
        return nil;
    }
    return keyData;
}

@end



公钥加密就用下面两个方法

+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey;
+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey;


级别: 新手上路
UID: 456810
精华: 0
发帖: 32
可可豆: 86 CB
威望: 86 点
在线时间: 127(时)
注册时间: 2015-04-01
最后登录: 2017-12-06
4 楼:  发表于: 2017-10-12 11:28    发自: Web Page
回 3楼(virus1993) 的帖子
我的公钥是一个base64加密的东西 用
static NSData *base64_decode(NSString *str){
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    return data;
}
这个方法解密之后得出的是一个140字节的nsdata 根本不能正常使用的
级别: 骑士
状态: 连续签到 - [3天]
UID: 362848
精华: 0
发帖: 328
可可豆: 379 CB
威望: 373 点
在线时间: 495(时)
注册时间: 2014-08-19
最后登录: 2017-12-15
5 楼:  发表于: 2017-10-12 11:36    发自: Web Page
base64 不是加密,只是一种编码方式
首先你要确定服务器返回的是什么,是base64编码的数据还是base64编码的字符串

级别: 新手上路
UID: 456810
精华: 0
发帖: 32
可可豆: 86 CB
威望: 86 点
在线时间: 127(时)
注册时间: 2015-04-01
最后登录: 2017-12-06
6 楼:  发表于: 2017-10-12 11:40    发自: Web Page
回 5楼(virus1993) 的帖子
MIGJAoGBANr9myYqWPw1NBzBnROnqbGukB04u4QQatVVyywiRrnnG0eYMETQveRMEdcbR4K1N9aaEWOwh+jzd5GE21UnN/guS9p9yMba5zfZIJ26+QHIh260hhNzydadT4UAwJ2hgRbGirBjg4/0qMQAXfoSVRTUGEFKLdv5i+unyB4zo+4LAgMBAAE=

就是这样一串东西
级别: 新手上路
UID: 456810
精华: 0
发帖: 32
可可豆: 86 CB
威望: 86 点
在线时间: 127(时)
注册时间: 2015-04-01
最后登录: 2017-12-06
7 楼:  发表于: 2017-10-12 11:41    发自: Web Page
是加密机返回出来的 他们所谓的公钥 就是这样的
级别: 新手上路
UID: 456810
精华: 0
发帖: 32
可可豆: 86 CB
威望: 86 点
在线时间: 127(时)
注册时间: 2015-04-01
最后登录: 2017-12-06
8 楼:  发表于: 2017-10-12 11:47    发自: Web Page
回 5楼(virus1993) 的帖子
是base64的数据来的 用这个字符串转化的nsdata 不能[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] 转化成字符串
级别: 骑士
状态: 连续签到 - [3天]
UID: 362848
精华: 0
发帖: 328
可可豆: 379 CB
威望: 373 点
在线时间: 495(时)
注册时间: 2014-08-19
最后登录: 2017-12-15
9 楼:  发表于: 2017-10-12 11:53    发自: Web Page
回 7楼(DanyCocoa) 的帖子
你要确定一下 他们原始的数据是不是字符串


NSString *base64String = @"MIGJAoGBANr9myYqWPw1NBzBnROnqbGukB04u4QQatVVyywiRrnnG0eYMETQveRMEdcbR4K1N9aaEWOwh+jzd5GE21UnN/guS9p9yMba5zfZIJ26+QHIh260hhNzydadT4UAwJ2hgRbGirBjg4/0qMQAXfoSVRTUGEFKLdv5i+unyB4zo+4LAgMBAAE=";
NSData *base64Data = [self base64_decode:base64String];
if (base64Data) {
        NSString *str = [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];
        NSLog(@"string: %@", str);
}



根据你的代码,得出str是 ni l,原始的数据不是 utf8 编码的字符串,所以你要跟后台确定base64编码之前是什么东西
描述
快速回复

关注本帖(如果有新回复会站内信通知您)

发帖、回帖都会得到可观的积分奖励。查看论坛积分规则

按"Ctrl+Enter"直接提交
    顶部