加密算法通常分为对称性加密算法和非对称性加密算法,以及线性散列算法,对应着比较常见的是 DES,RSA,MD5。
- 对称性加密算法,信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行加解密了。
- 非对称加密算法,发送双方A,B事先均生成一堆密匙,然后A将自己的公有密匙发送给B,B将自己的公有密匙发送给A,如果A要给B发送消 息,则先需要用B的公有密匙进行消息加密,然后发送给B端,此时B端再用自己的私有密匙进行消息解密,B向A发送消息时为同样的道理。
- 线性散列加密算法, 只生成一串不可逆的密文,经常用其效验数据传输过程中是否经过修改,因为相同的生成算法对于同一明文只会生成唯一的密文,若相同算法生成的密文不同,则证明传输数据进行过了修改。
3DES 和 MD5 是我用到过的,特此记录下。
3DES
3DES是一种基于DES的加密算法,使用3个不同密匙对同一个分组数据块进行3次加密,如此以使得密文强度更高。
当然一般我们现有的涉及到文件/信息加密,或提高数据安全级别一般都会选择 CommonCrypto
来完成任务。
可以从Oc 上面先了解它的函数声明:
CCCryptorStatus CCCrypt(
CCOperation op, // operation: kCCEncrypt or kCCDecrypt
CCAlgorithm alg, // algorithm: kCCAlgorithmAES128...
CCOptions options, // operation: kCCOptionPKCS7Padding...
const void *key, // key
size_t keyLength, // key length
const void *iv, // initialization vector (optional)
const void *dataIn, // input data
size_t dataInLength, // input data length
void *dataOut, // output data buffer
size_t dataOutAvailable, // output data length available
size_t *dataOutMoved) // real output data length generated
)
Swift + 3DES
extension String {
/**
3DES的加密过程 和 解密过程
- parameter op : CCOperation: 加密还是解密
CCOperation(kCCEncrypt)加密
CCOperation(kCCDecrypt) 解密
- parameter key: 专有的key,一个钥匙一般
- parameter iv : 可选的初始化向量,可以为nil
- returns : 返回加密或解密的参数
*/
func threeDESEncryptOrDecrypt(op: CCOperation,key: String,iv: String) -> String? {
// Key
let keyData: NSData = (key as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let keyBytes = UnsafeMutablePointer(keyData.bytes)
// 加密或解密的内容
var data: NSData = NSData()
if op == CCOperation(kCCEncrypt) {
data = (self as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
}
else {
data = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)!
}
let dataLength = size_t(data.length)
let dataBytes = UnsafeMutablePointer(data.bytes)
// 返回数据
let cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)
let cryptPointer = UnsafeMutablePointer(cryptData!.mutableBytes)
let cryptLength = size_t(cryptData!.length)
// 可选 的初始化向量
let viData :NSData = (iv as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let viDataBytes = UnsafeMutablePointer(viData.bytes)
// 特定的几个参数
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(op)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionPKCS7Padding)
var numBytesCrypted :size_t = 0
let cryptStatus = CCCrypt(operation, // 加密还是解密
algoritm, // 算法类型
options, // 密码块的设置选项
keyBytes, // 秘钥的字节
keyLength, // 秘钥的长度
viDataBytes, // 可选初始化向量的字节
dataBytes, // 加解密内容的字节
dataLength, // 加解密内容的长度
cryptPointer, // output data buffer
cryptLength, // output data length available
&numBytesCrypted) // real output data length
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData!.length = Int(numBytesCrypted)
if op == CCOperation(kCCEncrypt) {
let base64cryptString = cryptData!.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
return base64cryptString
}
else {
// let base64cryptString = NSString(bytes: cryptPointer, length: cryptLength, encoding: NSUTF8StringEncoding) as? String // 用这个会导致返回的JSON数据格式可能有问题,最好不用
let base64cryptString = NSString(data: cryptData!, encoding: NSUTF8StringEncoding) as? String
return base64cryptString
}
} else {
print("Error: \(cryptStatus)")
}
return nil
}
}
补充:
CCOperation
(操作)、CCAgorithm
(算法) 和 CCOptions
(设置)本质上就是 uint32_t
(一个占32位存储的 unsigned int
),所以我们可以通过 CommonCrypto
常量来构造它们。
let operation = CCOperation(kCCEncrypt)
let algorithm = CCAlgorithm(kCCAlgorithmAES) // 后面算法随你选择
let options = CCOptions(kCCOptionECBMode) // 设置项
附带一个Oc版的 3DES加解密 (此处没有用系统的base64,用的是GTMBase64)
+ (NSString*)TripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt key:(NSString*)key {
const void *vplainText;
size_t plainTextBufferSize;
if (encryptOrDecrypt == kCCDecrypt)
{
NSData *EncryptData = [GTMBase64 decodeData:[plainText dataUsingEncoding:NSUTF8StringEncoding]];
plainTextBufferSize = [EncryptData length];
vplainText = [EncryptData bytes];
}
else
{
NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
plainTextBufferSize = [data length];
vplainText = (const void *)[data bytes];
}
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
NSString *initVec = @"p2p_s2iv";
const void *vkey = (const void *) [key UTF8String];
const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(encryptOrDecrypt,
kCCAlgorithm3DES,
kCCOptionPKCS7Padding,
vkey, //"123456789012345678901234", //key
kCCKeySize3DES,
vinitVec, //"init Vec", //iv,
vplainText, //"Your Name", //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
NSString *result;
if (encryptOrDecrypt == kCCDecrypt)
{
result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr
length:(NSUInteger)movedBytes]
encoding:NSUTF8StringEncoding]
;
}
else
{
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [GTMBase64 stringByEncodingData:myData];
}
return result;
}
附带一个Swift 版的 Base64 + String
extension String {
//Encode base64
func base64Encoded() -> String {
let plainData = self.dataUsingEncoding(NSUTF8StringEncoding)
let base64String = plainData?.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
return base64String!
}
//Decode base64
func base64Decoded() -> String {
let decodedData = NSData(base64EncodedString: self, options: .IgnoreUnknownCharacters)
let decodedString = NSString(data: decodedData!, encoding: NSUTF8StringEncoding)
return decodedString! as String
}
}
MD5
MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。
swift + MD5
extension String {
var MD5: String! {
let str = self.cStringUsingEncoding(NSUTF8StringEncoding)
let strLen = CC_LONG(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
let digestLen = Int(CC_MD5_DIGEST_LENGTH)
let result = UnsafeMutablePointer.alloc(digestLen)
CC_MD5(str!, strLen, result)
let hash = NSMutableString()
for i in 0..
Oc + MD5
// 注意导入
#import
- (NSString *)MD5Hash
{
const char *cStr = [self UTF8String];
unsigned char result[16];
CC_MD5(cStr, (unsigned)strlen(cStr), result);
return [NSString stringWithFormat:
@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
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]];
}
一定要注意, Swift 剔除了 Objective-C 中属于 C 的部分,因此我们需要做一些准备工作才能在 Swift 和 Cocoa 中使用 CommonCrypto,我们需要在
Bridging-Header.h
中加入#import
。
备注参考
http://www.cnblogs.com/yangywyangyw/archive/2012/07/31/2620861.html
http://stackoverflow.com/questions/25754147/issue-using-cccrypt-commoncrypt-in-swift
http://www.itupup.com/?it09/525141.htm