一行代碼完成DES加密,加密模式 DES + CBChtml
最近項目中用到DES加密,在這裏整理成篇,供你們參考閱讀,在使用該demo過程當中,你可能會遇到一些問題,首先你須要看一下下面的demo簡介,看看該demo 是否適合你的項目。 項目中的DES加解密主要用在網絡請求過程當中對上傳的參數進行加密,對從後臺服務器獲取的數據進行解密。 總體的加密流程爲: 加密的過程: 參數字典 --> json字符串 --> base64加密後的字符串 --> DES加密後base64再加密 --> 輸出最終加密後的字符串; 解密的過程: 後臺服務器獲取加密的字符串 -->base64解密 --> DES解密後base64解密 --> json字符串 --> 數據字典;(與加密的過程相反) 網上對DES的詳細介紹已經有不少,在這裏不作贅述,若是你須要瞭解這些知識,google.
咱們公司後臺爲JAVA,移動端有iOS與Android, 討論後選擇DES的加密模式爲 DES + CBC (注意是否知足你的加密需求)。 爲何選擇這種加密模式: 若是採用PKCS7Padding或者PKCS5Padding這種加密方式,末端添加的數據可能不固定,在解碼後須要把末端多餘的字符去掉,比較棘手。 若是無論補齊多少位,末端都是'\0',去掉的話比較容易操做。 最主要的是能使得 iOS/Android/PHP相互通訊,也是加密過程當中最難搞的地方,尤爲須要開發者注意。 項目中用到了 google 的 base64 加解密庫 GTMBase64,可是這個庫已經有不少年沒有更新 仍是 MRC 開發模式,須要手動配置一下: 1.選擇項目中的Targets,選中你所要操做的Target, 2.選Build Phases,在其中Complie Sources中選擇須要ARC的文件雙擊,並在輸入框中輸入 -fno-objc-arc
//加密 /// 加密 NSMutableDictionary *dic=[NSMutableDictionary dictionary]; [dic setValue:@"111111" forKey:@"password"]; [dic setValue:@"admin" forKey:@"userName"]; /* 加密{"userName":"admin","password":"111111"}和 { "userName" : "admin", "password" : "111111" } 加密後結果是不同的,必定要肯定公司後臺是怎麼加密的,要否則有可能會錯誤 */ NSString *jsonstr = [dic JSONString]; self.lb_show.text = [EncryptUtil encryptUseDES:jsonstr key:gkey]; //加密結果 iMXucxT4Z6v0ZILRJtUX1W/8KfR1wvqqdDxHiOdfTvkdVQQnJ7p1DdMPQXM60BwNHBdjhTqbnXIN eEYVIHbb6w==
//解密 - (IBAction)clickDecodeBtn:(UIButton *)sender { //上面加密的結果 NSString *AESString = @"iMXucxT4Z6v0ZILRJtUX1W/8KfR1wvqqdDxHiOdfTvkdVQQnJ7p1DdMPQXM60BwNHBdjhTqbnXIN eEYVIHbb6w=="; ///解密 self.lb_show.text = [EncryptUtil decryptUseDES:self.lb_show.text key:gkey]; 解密結果:{"userName":"admin","password":"111111"} }
java /** * <li> * 方法名稱:encrypt</li> <li> * 加密方法 * @param xmlStr * 須要加密的消息字符串 * @return 加密後的字符串 */ public static String encrypt(String xmlStr) { byte[] encrypt = null; try { // 取須要加密內容的utf-8編碼。 encrypt = xmlStr.getBytes("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 取MD5Hash碼,並組合加密數組 byte[] md5Hasn = null; try { // md5Hash = EncryptUtil.MD5Hash(temp, 16, temp.length - 16); md5Hasn = EncryptUtil.MD5Hash(encrypt, 0, encrypt.length); } catch (Exception e) { e.printStackTrace(); } // 組合消息體 byte[] totalByte = EncryptUtil.addMD5(md5Hasn, encrypt); // 取密鑰和偏轉向量 byte[] key = new byte[8]; byte[] iv = new byte[8]; getKeyIV(EncryptUtil.key, key, iv); SecretKeySpec deskey = new SecretKeySpec(key, "DES"); IvParameterSpec ivParam = new IvParameterSpec(iv); // 使用DES算法使用加密消息體 byte[] temp = null; try { temp = EncryptUtil.DES_CBC_Encrypt(totalByte, deskey, ivParam); } catch (Exception e) { e.printStackTrace(); } // 使用Base64加密後返回 return new BASE64Encoder().encode(temp); } ios /// 加密方法 + (NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key { /// 轉換成data NSData* plainTextdata = [plainText dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger plainTextdatLength = [plainTextdata length]; /// 將data數據MD5加密 unsigned char digest[16]; CC_MD5([plainTextdata bytes],(CC_LONG) plainTextdatLength, digest); // 總長度 MD5 + plainText NSUInteger plainTextBufferTotalSize = 16 +plainTextdatLength; // 將plainText 轉換成bytes Byte *testByte = (Byte *)[plainTextdata bytes]; // 定義totalByte Byte totalByte[plainTextBufferTotalSize]; for (int i = 0; i < plainTextBufferTotalSize; ++i) { if (i<16) { totalByte[i] =digest[i]; }else{ totalByte[i] =testByte[i - 16]; } } /// 將key base64 編碼 NSData *baseKey = [GTMBase64 decodeString:key]; Byte *buf = (Byte *)[baseKey bytes]; Byte key1[8]; Byte iv2[8]; for (int i = 0; i < 8; i++) { key1[i] = buf[i]; } // // 後8位爲iv向量 for (int i = 0; i < 8 ; i++) { iv2[i] = buf[i + 8]; } NSString *ciphertext = nil; unsigned char buffer[1024]; memset(buffer, 0, sizeof(char)); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding, key1, kCCKeySizeDES, iv2, totalByte, plainTextBufferTotalSize, buffer, 1024, &numBytesEncrypted); if (cryptStatus == kCCSuccess) { NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted]; ciphertext = [[NSString alloc] initWithData:[GTMBase64 encodeData:data] encoding:NSUTF8StringEncoding]; } return ciphertext; }
java 解密 /** * <li> * 方法名稱:encrypt</li> <li> * 功能描述: * * <pre> * 解密方法 * </pre> * * </li> * * @param xmlStr * 須要解密的消息字符串 * @return 解密後的字符串 * @throws Exception */ public static String decrypt(String xmlStr) throws Exception { // base64解碼 BASE64Decoder decoder = new BASE64Decoder(); byte[] encBuf = null; try { encBuf = decoder.decodeBuffer(xmlStr); } catch (IOException e) { e.printStackTrace(); } // 取密鑰和偏轉向量 byte[] key = new byte[8]; byte[] iv = new byte[8]; getKeyIV(EncryptUtil.key, key, iv); SecretKeySpec deskey = new SecretKeySpec(key, "DES"); IvParameterSpec ivParam = new IvParameterSpec(iv); // 使用DES算法解密 byte[] temp = null; try { temp = EncryptUtil.DES_CBC_Decrypt(encBuf, deskey, ivParam); } catch (Exception e) { e.printStackTrace(); } // 進行解密後的md5Hash校驗 byte[] md5Hash = null; try { md5Hash = EncryptUtil.MD5Hash(temp, 16, temp.length - 16); } catch (Exception e) { e.printStackTrace(); } // 進行解密校檢 for (int i = 0; i < md5Hash.length; i++) { if (md5Hash[i] != temp[i]) { // System.out.println(md5Hash[i] + "MD5校驗錯誤。" + temp[i]); throw new Exception("MD5校驗錯誤。"); } } // 返回解密後的數組,其中前16位MD5Hash碼要除去。 return new String(temp, 16, temp.length - 16, "utf-8"); } ios 解密 /// 解密方法 + (NSString *) decryptUseDES:(NSString *)plainText key:(NSString *)key { // plainTextData轉換 base64 NSData *BasePlainTextData = [GTMBase64 decodeString:plainText]; // 將BasePlainTextDatabase64轉換爲byte數組 Byte *BasePlainTextDataByte = (Byte *)[BasePlainTextData bytes]; // 將key base64解碼 NSData *baseKey = [GTMBase64 decodeString:key]; // 將key 轉換成 byte數組 Byte *buf = (Byte *)[baseKey bytes]; // 定義key iv byte數組 Byte keyByte[8]; Byte ivByte[8]; for (int i = 0; i < 8; i++) { keyByte[i] = buf[i]; } // // 後8位爲iv向量 for (int i = 0; i < 8 ; i++) { ivByte[i] = buf[i + 8]; } /// 返回值長度 size_t bufferSize = BasePlainTextData.length; // 字符串長度比較長 返回值給大點 unsigned char buffer[1024]; memset(buffer,0,sizeof(char)); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding, keyByte, kCCKeySizeDES, ivByte, BasePlainTextDataByte, bufferSize, buffer, 1024, &numBytesEncrypted); NSData *resultdata; if (cryptStatus == kCCSuccess) { resultdata = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted]; } Byte *resultByte = (Byte *)[resultdata bytes]; // 返回數組長度 減去MD5加密的16 size_t returnLength = resultdata.length - 16; /// 定義 Byte decryptionByte[returnLength]; for (int i = 0; i < returnLength; ++i) { decryptionByte[i] = resultByte[i+16]; } /// md5 校驗 // unsigned char digest[16]; // CC_MD5(decryptionByte,returnLength, digest); // NSData *md5data = [NSData dataWithBytes:digest length:16]; // 進行解密校檢 // Byte *md5bte= (Byte *)[md5data bytes]; // for (int i = 0; i < 40; i++) { // // // if (md5bte[i] !=decryptionByte[i] ) { // // System.out.println(md5Hash[i] + "MD5校驗錯誤。" + temp[i]); // // throw new Exception("MD5校驗錯誤。"); // // NSLog(@"c1111uowu"); // }else{ // NSLog(@"cuowu"); // } // } NSData *namedata = [[NSData alloc] initWithBytes:decryptionByte length:returnLength]; NSString *str = [[NSString alloc] initWithData:namedata encoding:NSUTF8StringEncoding]; NSLog(@"%@",str); return str; }
項目中遇到的一些坑,在 DEMO 中都已經註釋出來,寫的比較清楚,若是該 DEMO 幫助了您,也但願能給個 starjava
鼓勵一下,若是在使用中您有任何問題,能夠在 github issues,我會盡本身能力給您答覆 。ios
在這裏感謝這些 blog 的做者,讓我在開發過程當中少走了不少彎路: [http://www.open-open.com/lib/view/open1452738808948.html) [https://my.oschina.net/jsan/blog/54385) [http://blog.csdn.net/j_akill/article/details/44079597](http://blog.csdn.net/j_akill/article/details/44079597) [http://blog.csdn.net/jbjwpzyl3611421/article/details/18256917) [https://github.com/IMCCP/CCPAESEncode/blob/master/CCPAESEncode)