美文网首页iOS
iOS 中使用sha1withRSA加密字符串

iOS 中使用sha1withRSA加密字符串

作者: 微笑不是你 | 来源:发表于2018-12-26 19:09 被阅读0次

    一.导入系统文件

    #import <CommonCrypto/CommonDigest.h>
    #import <CommonCrypto/CommonCryptor.h>
    #import <Security/Security.h>
    

    配置宏

    #define kChosenDigestLength CC_SHA1_DIGEST_LENGTH // SHA-1消息摘要的数据位数160位
    #define kPrivateKey @"你的私钥"
    #define kPublicKey @"你的公钥"
    

    SHA1+RSA 签名

    signSHA1WithRSA 为加签

    verifySHA1WithRSA 为验签 验签返回1为正确

    + (NSString *)signSHA1WithRSA:(NSString *)plainText{
    
    uint8_t* signedBytes = NULL;
    
    size_t signedBytesSize = 0;
    
    OSStatus sanityCheck = noErr;
    
    NSData* signedHash = nil;
    
    SecKeyRef privateKeyRef = [self addPrivateKey:kPrivateKey];
    
    signedBytesSize = SecKeyGetBlockSize(privateKeyRef);
    
    NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    
    signedBytes = malloc( signedBytesSize * sizeof(uint8_t) );
    
    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 = [self base64EncodeData:signedHash];
    
    return signatureResult;
    
    }
    
    
    
    
    + (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;
    
    }
    
    
    
    
    #pragma mark - SHA1+RSA 验签
    
    + (NSString *)signSHA1WithRSA:(NSString *)plainText{
    
    uint8_t* signedBytes = NULL;
    
    size_t signedBytesSize = 0;
    
    OSStatus sanityCheck = noErr;
    
    NSData* signedHash = nil;
    
    SecKeyRef privateKeyRef = [self addPrivateKey:kPrivateKey];
    
    signedBytesSize = SecKeyGetBlockSize(privateKeyRef);
    
    NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    
    signedBytes = malloc( signedBytesSize * sizeof(uint8_t) );
    
    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 = [self base64EncodeData:signedHash];
    
    return signatureResult;
    
    }
    
    
    
    
    + (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);
    
    hash = [NSData dataWithBytes:(const void  *)hashBytes length:(NSUInteger)kChosenDigestLength];
    
    if (hashBytes) free(hashBytes);
    
    return hash;
    
    }
    
    #pragma mark - SHA1+RSA 验签
    
    + (BOOL)verifySHA1WithRSA:(NSString *)plainString signature:(NSString *)signatureString{
    
    NSData *plainData = [plainString dataUsingEncoding:NSUTF8StringEncoding];
    
    NSData *signatureData = [self base64DecodeString:signatureString];
    
    SecKeyRef publicKey = [self addPublicKey:kPublicKey];
    
    size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);
    
    const void* signedHashBytes = [signatureData bytes];
    
    size_t hashBytesSize = CC_SHA1_DIGEST_LENGTH;
    
    uint8_t* hashBytes = malloc(hashBytesSize);
    
    if (!CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
    
    return NO;
    
    }
    
    OSStatus status = SecKeyRawVerify(publicKey,
    
    kSecPaddingPKCS1SHA1,
    
    hashBytes,
    
    hashBytesSize,
    
    signedHashBytes,
    
    signedHashBytesSize);
    
    return status == errSecSuccess;
    
    }
    
    
    
    
    #pragma mark - Base64
    
    + (NSString *)base64EncodeData:(NSData *)data{
    
    data = [data base64EncodedDataWithOptions:0];
    
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    return ret;
    
    }
    
    
    
    
    + (NSData *)base64DecodeString:(NSString *)string{
    
    NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters];
    
    return data;
    
    }
    
    
    
    
    + (SecKeyRef)addPrivateKey:(NSString *)key{
    
    NSRange spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
    
    NSRange epos = [key rangeOfString:@"-----END RSA 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:@""];
    
    NSData *data = base64_decode(key);
    
    data = [self stripPrivateKeyHeader:data];
    
    if(!data){
    
    return nil;
    
    }
    
    NSString *tag = @"RSAUtil_PrivKey";
    
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
    
    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);
    
    [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];
    
    SecKeyRef keyRef = nil;
    
    status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
    
    if(status != noErr){
    
    return nil;
    
    }
    
    return keyRef;
    
    }
    
    static NSData *base64_decode(NSString *str){
    
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    
    return data;
    
    }
    
    
    
    + (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 = [self 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;
    
    }
    
    
    
    + (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]);
    
    }
    

    相关文章

      网友评论

        本文标题:iOS 中使用sha1withRSA加密字符串

        本文链接:https://www.haomeiwen.com/subject/wtjklqtx.html