iOS 中 3DES加密、MD5加密

加密算法通常分為對稱性加密算法和非對稱性加密算法憋肖,以及線性散列算法因痛,對應(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鲤妥,一起剝皮案震驚了整個濱河市佳吞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棉安,老刑警劉巖底扳,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贡耽,居然都是意外死亡衷模,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進店門蒲赂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阱冶,“玉大人,你說我怎么就攤上這事滥嘴∧镜牛” “怎么了?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵若皱,是天一觀的道長镊叁。 經(jīng)常有香客問我,道長走触,這世上最難降的妖魔是什么意系? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮饺汹,結(jié)果婚禮上蛔添,老公的妹妹穿的比我還像新娘。我一直安慰自己兜辞,他們只是感情好迎瞧,可當(dāng)我...
    茶點故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逸吵,像睡著了一般凶硅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扫皱,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天足绅,我揣著相機與錄音捷绑,去河邊找鬼。 笑死氢妈,一個胖子當(dāng)著我的面吹牛粹污,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播首量,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼壮吩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了加缘?” 一聲冷哼從身側(cè)響起鸭叙,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拣宏,沒想到半個月后沈贝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡勋乾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年宋下,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片市俊。...
    茶點故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡杨凑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出摆昧,到底是詐尸還是另有隱情撩满,我是刑警寧澤,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布绅你,位于F島的核電站伺帘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏忌锯。R本人自食惡果不足惜伪嫁,卻給世界環(huán)境...
    茶點故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望偶垮。 院中可真熱鬧张咳,春花似錦、人聲如沸似舵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砚哗。三九已至龙助,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛛芥,已是汗流浹背提鸟。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工军援, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人称勋。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓胸哥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铣缠。 傳聞我的和親對象是個殘疾皇子烘嘱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,595評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 隨著對于安全度的不斷要求捡硅,對于數(shù)據(jù)加解密與破解之間的斗爭,加解密的方式也在不斷發(fā)生著變化盗棵,來看看現(xiàn)在流行的一些加解...
    zhouhao_180閱讀 2,073評論 1 12
  • 這篇文章不是研究性的東西屯曹,主要是簡單的一些知識, 開篇如此惊畏, 我盡量不讓讀者失望恶耽。 首先羅列一些知識點:1.加密算...
    SOI閱讀 7,262評論 3 70
  • 本文主要介紹移動端的加解密算法的分類、其優(yōu)缺點特性及應(yīng)用颜启,幫助讀者由淺入深地了解和選擇加解密算法偷俭。文中會包含算法的...
    蘋果粉閱讀 11,475評論 5 29
  • 還記得孩子時候的我特別愛幻想,每個女孩小的時候都特別期待白馬王子缰盏,騎著一匹雪白的馬涌萤,走在綠綠的草地上,緩緩的向...
    夢雅星辰閱讀 265評論 0 0
  • this對象 this總是返回一個對象口猜,也就是返回屬性或者方法當(dāng)前所在的對象负溪。可以近似地認為暮的,this是所有函數(shù)在...
    LeoCong閱讀 177評論 0 0