加密算法通常分為對稱性加密算法和非對稱性加密算法憋肖,以及線性散列算法因痛,對應(yīng)著比較常見的是 DES,RSA岸更,MD5鸵膏。
- 對稱性加密算法,信息接收雙方都需事先知道密匙和加解密算法且其密匙是相同的怎炊,之后便是對數(shù)據(jù)進行加解密了谭企。
- 非對稱加密算法廓译,發(fā)送雙方A,B事先均生成一堆密匙,然后A將自己的公有密匙發(fā)送給B债查,B將自己的公有密匙發(fā)送給A非区,如果A要給B發(fā)送消 息,則先需要用B的公有密匙進行消息加密盹廷,然后發(fā)送給B端征绸,此時B端再用自己的私有密匙進行消息解密,B向A發(fā)送消息時為同樣的道理俄占。
- 線性散列加密算法歹垫, 只生成一串不可逆的密文,經(jīng)常用其效驗數(shù)據(jù)傳輸過程中是否經(jīng)過修改颠放,因為相同的生成算法對于同一明文只會生成唯一的密文排惨,若相同算法生成的密文不同,則證明傳輸數(shù)據(jù)進行過了修改碰凶。
3DES 和 MD5 是我用到過的暮芭,特此記錄下。
3DES
3DES是一種基于DES的加密算法欲低,使用3個不同密匙對同一個分組數(shù)據(jù)塊進行3次加密辕宏,如此以使得密文強度更高。
當(dāng)然一般我們現(xiàn)有的涉及到文件/信息加密砾莱,或提高數(shù)據(jù)安全級別一般都會選擇 CommonCrypto
來完成任務(wù)瑞筐。
可以從Oc 上面先了解它的函數(shù)聲明:
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 : 返回加密或解密的參數(shù)
*/
func threeDESEncryptOrDecrypt(op: CCOperation,key: String,iv: String) -> String? {
// Key
let keyData: NSData = (key as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let keyBytes = UnsafeMutablePointer<Void>(keyData.bytes)
// 加密或解密的內(nèi)容
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<Void>(data.bytes)
// 返回數(shù)據(jù)
let cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)
let cryptPointer = UnsafeMutablePointer<Void>(cryptData!.mutableBytes)
let cryptLength = size_t(cryptData!.length)
// 可選 的初始化向量
let viData :NSData = (iv as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!
let viDataBytes = UnsafeMutablePointer<Void>(viData.bytes)
// 特定的幾個參數(shù)
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, // 密碼塊的設(shè)置選項
keyBytes, // 秘鑰的字節(jié)
keyLength, // 秘鑰的長度
viDataBytes, // 可選初始化向量的字節(jié)
dataBytes, // 加解密內(nèi)容的字節(jié)
dataLength, // 加解密內(nèi)容的長度
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 // 用這個會導(dǎo)致返回的JSON數(shù)據(jù)格式可能有問題腊瑟,最好不用
let base64cryptString = NSString(data: cryptData!, encoding: NSUTF8StringEncoding) as? String
return base64cryptString
}
} else {
print("Error: \(cryptStatus)")
}
return nil
}
}
補充:
CCOperation
(操作)聚假、CCAgorithm
(算法) 和 CCOptions
(設(shè)置)本質(zhì)上就是 uint32_t
(一個占32位存儲的 unsigned int
),所以我們可以通過 CommonCrypto
常量來構(gòu)造它們闰非。
let operation = CCOperation(kCCEncrypt)
let algorithm = CCAlgorithm(kCCAlgorithmAES) // 后面算法隨你選擇
let options = CCOptions(kCCOptionECBMode) // 設(shè)置項
附帶一個Oc版的 3DES加解密 (此處沒有用系統(tǒng)的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位子分組,經(jīng)過了一系列的處理后财松,算法的輸出由四個32位分組組成瘪贱,將這四個32位分組級聯(lián)后將生成一個128位散列值。
MD5的典型應(yīng)用是對一段Message(字節(jié)串)產(chǎn)生fingerprint(指紋)辆毡,以防止被“篡改”菜秦。舉個例子,你將一段話寫在一個叫 readme.txt文件中舶掖,并對這個readme.txt產(chǎn)生一個MD5的值并記錄在案球昨,然后你可以傳播這個文件給別人,別人如果修改了文件中的任何內(nèi)容访锻,你對這個文件重新計算MD5時就會發(fā)現(xiàn)褪尝。如果再有一個第三方的認證機構(gòu)闹获,用MD5還可以防止文件作者的“抵賴”期犬,這就是所謂的數(shù)字簽名應(yīng)用河哑。
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<CUnsignedChar>.alloc(digestLen)
CC_MD5(str!, strLen, result)
let hash = NSMutableString()
for i in 0..<digestLen {
hash.appendFormat("%02x", result[i])
}
result.dealloc(digestLen)
return String(format: hash as String)
}
}
Oc + MD5
// 注意導(dǎo)入
#import <CommonCrypto/CommonDigest.h>
- (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 的部分龟虎,因此我們需要做一些準(zhǔn)備工作才能在 Swift 和 Cocoa 中使用 CommonCrypto璃谨,我們需要在
Bridging-Header.h
中加入#import <CommonCrypto/CommonCrypto.h>
。
備注參考
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