NSString 加密、 MD5

#import <CommonCrypto/CommonDigest.h>


//TODO: md5 加密方法

- (NSString *)md5Digest:(NSString *)str{

const char *cStr = [str UTF8String];

    unsigned char result[CC_MD5_DIGEST_LENGTH];

    CC_MD5(cStr, strlen(cStr), result);

    return [NSString stringWithFormat:

            @"XXXXXXXXXXXXXXXX",

            result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],

            result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]

            ];

}



相关知识链接一(百度百科):


1. 什么是md5

md5,全称叫 Message Digest Algorithm MD5,中文名为消息摘要算法第五版,是一种散列函数,用以提供消息的完整性保护。


背景

  在90年代初由MIT Laboratory for Computer ScienceRSA Data Security Ic,Ronald L. Rivest开发出来,经MD2MD3MD4发展而来。它的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。不管是MD2MD4还是MD5,它们都需要获得一个随机长度的信息并产生一个128位的信息摘要。虽然这些算法的结构或多或少有些相似,但MD2的设计与MD4MD5完全不同,那是因为MD2是为8位机器做设计优化的,而MD4MD5却是面向32位的电脑。这三个算法的描述和c语言源代码Internet RFC 1321中有详细的描述,这是一份最权威的文档,由Ronald L. Rivest19928月向IETF提交。


 MD5最广泛被用于各种软件的密码认证和钥匙识别上。通俗的讲就是人们讲的序列号。


 MD5用的是哈希函数,在计算机网络中应用较多的不可逆加密算法RSA公司发明的MD5算法和由美国国家技术标准研究所建议的安全散列算法SHA


2.  md5的应用

数字签名

  MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被篡改。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现(两个MD5值不相同)。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的抵赖,这就是所谓的数字签名应用。


登录认证

  MD5还广泛用于操作系统的登陆认证上,如Unix、各类BSD系统登录密码、数字签名等诸多方。如在UNIX系统中用户的密码是以MD5(或其它类似的算法)经Hash运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这可以避免用户的密码被具有系统管理员权限的用户知道。MD5将任意长度的字节串映射为一个128bit的大整数,并且是通过该128bit反推原始字符串是困难的,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。


3.  MD5的破解

2004817日的美国加州圣巴巴拉的国际密码学会议(Crypto’2004)上,来自中国山东大学的王小云教授做了破译MD5HAVAL-128、 MD4RIPEMD算法的报告,公布了MD系列算法的破解结果。宣告了固若金汤的世界通行密码标准MD5的堡垒轰然倒塌,引发了密码学界的轩然大波。

王小云的研究成果表明了从理论上讲电子签名可以伪造,必须及时添加限制条件,或者重新选用更为安全的密码标准,以保证电子商务的安全。


王小云及其研究同工展示了MD5SHA-0及其他相关杂凑函数的杂凑冲撞。所谓杂凑冲撞指两个完全不同的讯息经杂凑函数计算得出完全相同的杂凑值。根据鸽巢原理,以有长度限制的杂凑函数计算没有长度限制的讯息是必然会有冲撞情况出现的。可是,一直以来,电脑保安专家都认为要任意制造出冲撞需时太长,在实际情况上不可能发生,而王小云等的发现可能会打破这个必然性。就这样,王小云在国际会议上首次宣布了她及她的研究小组近年来的研究成果——MD4MD5HAVAL-128RIPEMD等四个著名密码算法的破译结果。


4.  MD5 是否安全

信息安全国家重点实验室教授、密码学专家翟起滨:“MD5SHA-1属于散列算法,从设计原理来讲,就有产生碰撞的可能,王小云教授的方法缩短了找到碰撞的时间,是一项重要的成果。但她找到的是强无碰撞,要能找到弱无碰撞,才算真正破解,才有实际意义。碰撞分为强无碰撞弱无碰撞。强无碰撞是无法产生有实际意义的原文的,也就无法篡改和伪造出有意义的明文。通过强无碰撞伪造一个谁也看不懂的东西,没有实际意义。


翟教授还让记者浏览了“RSA 2005”年会的会议摘要,国际密码学专家沙米尔(Shamir)在“RSA 2005”年会上就王小云教授找到一对强无碰撞发表观点:这是个重要的事情,但不意味着密码被破解。


什么叫碰撞:
  根据密码学的定义,如果内容不同的明文,通过散列算法得出的结果(密码学称为信息摘要)相同,就称为发生了碰撞。碰撞分为强无碰撞弱无碰撞’,强无碰撞是无法产生有实际意义原文;弱无碰撞是对你想伪造的明文,进行运算得出相同的摘要信息。



链接二:

数字签名与验证过程
  网上通信的双方,在互相认证身份之后,即可发送签名的数据电文。数字签名的全过程分两大部分,即签名与验证。

数字签名操作过程
  数字签名操作具体过程如下:首先是生成被签名的电子文件(《电子签名法》中称数据电文),然后对电子文件用散列算法做数字摘要,再对数字摘要用签名私钥做非对称加密,即作数字签名;之后是将以上的签名和电子文件原文以及签名证书的公钥加在一起进行封装,形成签名结果发送给收方,待收方验证。


数字签名验证过程
  接收方收到数字签名的结果,其中包括数字签名、电子原文和发方公钥,接收方进行签名验证。验证过程是:接收方首先用发方公钥解密数字签名,导出数字摘要,并对电子文件原文做同样散列算法得出一个新的数字摘要;将两个摘要进行结果比较,结果相同则签名得到验证,否则签名无效。这就做到了《电子签名法》中所要求的对签名不能改动,对签署的内容和形式也不能改动的要求。


#import <Foundation/Foundation.h>


@class NSString;


@interface NSData (Encryption)


- (NSData *)AES256EncryptWithKey:(NSString *)key;   //加密

- (NSData *)AES256DecryptWithKey:(NSString *)key;   //解密

- (NSString *)newStringInBase64FromData;            //追加64编码

+ (NSString*)base64encode:(NSString*)str;           //同上64编码

@end



//

//  Encryption.m

//  

//

//  Created by zhangxiaohui on 11-6-1.

//  Copyright 2011 __MyCompanyName__. All rights reserved.

//


#import "Encryption.h"

#import <CommonCrypto/CommonCryptor.h>



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


@implementation NSData (Encryption)


- (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(kCCEncryptkCCAlgorithmAES128,

                                          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(kCCDecryptkCCAlgorithmAES128,

                                          kCCOptionPKCS7Padding | kCCOptionECBMode,

                                          keyPtr, kCCBlockSizeAES128,

                                          NULL,

                                          [self bytes], dataLength,

                                          buffer, bufferSize,

                                          &numBytesDecrypted);

    if (cryptStatus == kCCSuccess) {

        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];

    }

    free(buffer);

return nil;

}



- (NSString *)newStringInBase64FromData            //追加64编码

{

NSMutableString *dest = [[NSMutableString allocinitWithString:@""];

    unsigned char * working = (unsigned char *)[self bytes];

    int srcLen = [self length];

    for (int i=0; i<srcLen; i += 3) {

        for (int nib=0; nib<4; nib++) {

            int byt = (nib == 0)?0:nib-1;

            int ix = (nib+1)*2;

            if (i+byt >= srcLen) break;

            unsigned char curr = ((working[i+byt] << (8-ix)) & 0x3F);

            if (i+nib < srcLen) curr |= ((working[i+nib] >> ix) & 0x3F);

            [dest appendFormat:@"%c"base64[curr]];

        }

    }

    return dest;

}


+ (NSString*)base64encode:(NSString*)str

{

if ([str length] == 0)

return @"";

const char *source = [str UTF8String];

int strlength  = strlen(source);

char *characters = malloc(((strlength + 2) / 3) * 4);

if (characters == NULL)

return nil;

NSUInteger length = 0;

NSUInteger i = 0;

while (i < strlength) {

char buffer[3] = {0,0,0};

short bufferLength = 0;

while (bufferLength < 3 && i < strlength)

buffer[bufferLength++] = source[i++];

characters[length++] = base64[(buffer[0] & 0xFC) >> 2];

characters[length++] = base64[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >>4)];

if (bufferLength > 1)

characters[length++] = base64[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >>6)];

else characters[length++] = '=';

if (bufferLength > 2)

characters[length++] = base64[buffer[2] & 0x3F];

else characters[length++] = '=';

}

NSString *g = [[[NSString allocinitWithBytesNoCopy:characters length:lengthencoding:NSASCIIStringEncoding freeWhenDone:YESautorelease];

return g;

}



@end



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值