DES 加密 解密
EncryptUtil
feiyangklDES
一行代碼完成DES加密,加密模式 DES + CBC
DEMO GIF
DEMO 簡介
最近項(xiàng)目中用到DES加密,在這里整理成篇,供大家參考閱讀,在使用該demo過程中,你可能會(huì)遇到一些問題,首先你需要看一下下面的demo簡介,看看該demo 是否適合你的項(xiàng)目。項(xiàng)目中的DES加解密主要用在網(wǎng)絡(luò)請(qǐng)求過程中對(duì)上傳的參數(shù)進(jìn)行加密,對(duì)從后臺(tái)服務(wù)器獲取的數(shù)據(jù)進(jìn)行解密。整體的加密流程為:加密的過程: 參數(shù)字典 --> json字符串 --> base64加密后的字符串 --> DES加密后base64再加密 --> 輸出最終加密后的字符串;解密的過程: 后臺(tái)服務(wù)器獲取加密的字符串 -->base64解密 --> DES解密后base64解密 --> json字符串 --> 數(shù)據(jù)字典;(與加密的過程相反)網(wǎng)上對(duì)DES的詳細(xì)介紹已經(jīng)有很多,在這里不做贅述,如果你需要了解這些知識(shí),google. 我們公司后臺(tái)為JAVA,移動(dòng)端有iOS與Android, 討論后選擇DES的加密模式為 DES + CBC (注意是否滿足你的加密需求)。為什么選擇這種加密模式:如果采用PKCS7Padding或者PKCS5Padding這種加密方式,末端添加的數(shù)據(jù)可能不固定,在解碼后需要把末端多余的字符去掉,比較棘手。如果不管補(bǔ)齊多少位,末端都是'\0',去掉的話比較容易操作。 最主要的是能使得iOS/Android/PHP相互通信,也是加密過程中最難搞的地方,尤其需要開發(fā)者注意。項(xiàng)目中用到了 google 的 base64 加解密庫 GTMBase64,但是這個(gè)庫已經(jīng)有很多年沒有更新 還是 MRC 開發(fā)模式,需要手動(dòng)配置一下:1.選擇項(xiàng)目中的Targets,選中你所要操作的Target,2.選Build Phases,在其中Complie Sources中選擇需要ARC的文件雙擊,并在輸入框中輸入 -fno-objc-arcDEMO 使用示例
//加密/// 加密 NSMutableDictionary *dic=[NSMutableDictionary dictionary]; [dic setValue:@"111111" forKey:@"password"]; [dic setValue:@"admin" forKey:@"userName"];/* 加密{"userName":"admin","password":"111111"}和 { "userName" : "admin", "password" : "111111" } 加密后結(jié)果是不一樣的,一定要確定公司后臺(tái)是怎么加密的,要不然有可能會(huì)錯(cuò)誤 */ NSString *jsonstr = [dic JSONString]; self.lb_show.text = [EncryptUtil encryptUseDES:jsonstr key:gkey];//加密結(jié)果 iMXucxT4Z6v0ZILRJtUX1W/8KfR1wvqqdDxHiOdfTvkdVQQnJ7p1DdMPQXM60BwNHBdjhTqbnXIN eEYVIHbb6w== //解密- (IBAction)clickDecodeBtn:(UIButton *)sender {//上面加密的結(jié)果 NSString *AESString = @"iMXucxT4Z6v0ZILRJtUX1W/8KfR1wvqqdDxHiOdfTvkdVQQnJ7p1DdMPQXM60BwNHBdjhTqbnXIN eEYVIHbb6w==";///解密 self.lb_show.text = [EncryptUtil decryptUseDES:self.lb_show.text key:gkey];解密結(jié)果:{"userName":"admin","password":"111111"}} java /** * <li> * 方法名稱:encrypt</li> <li> * 加密方法 * @param xmlStr * 需要加密的消息字符串 * @return 加密后的字符串 */ public static String encrypt(String xmlStr) { byte[] encrypt = null;try { // 取需要加密內(nèi)容的utf-8編碼。 encrypt = xmlStr.getBytes("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 取MD5Hash碼,并組合加密數(shù)組 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);// 取密鑰和偏轉(zhuǎn)向量 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 { /// 轉(zhuǎn)換成data NSData* plainTextdata = [plainText dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger plainTextdatLength = [plainTextdata length]; /// 將data數(shù)據(jù)MD5加密 unsigned char digest[16]; CC_MD5([plainTextdata bytes],(CC_LONG) plainTextdatLength, digest);// 總長度 MD5 + plainText NSUInteger plainTextBufferTotalSize = 16 +plainTextdatLength;// 將plainText 轉(zhuǎn)換成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(); }// 取密鑰和偏轉(zhuǎn)向量 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(); }// 進(jìn)行解密后的md5Hash校驗(yàn) byte[] md5Hash = null; try { md5Hash = EncryptUtil.MD5Hash(temp, 16, temp.length - 16); } catch (Exception e) { e.printStackTrace(); }// 進(jìn)行解密校檢 for (int i = 0; i < md5Hash.length; i++) { if (md5Hash[i] != temp[i]) { // System.out.println(md5Hash[i] + "MD5校驗(yàn)錯(cuò)誤。" + temp[i]); throw new Exception("MD5校驗(yàn)錯(cuò)誤。"); } }// 返回解密后的數(shù)組,其中前16位MD5Hash碼要除去。 return new String(temp, 16, temp.length - 16, "utf-8"); }ios 解密/// 解密方法 + (NSString *) decryptUseDES:(NSString *)plainText key:(NSString *)key {// plainTextData轉(zhuǎn)換 base64 NSData *BasePlainTextData = [GTMBase64 decodeString:plainText]; // 將BasePlainTextDatabase64轉(zhuǎn)換為byte數(shù)組 Byte *BasePlainTextDataByte = (Byte *)[BasePlainTextData bytes];// 將key base64解碼 NSData *baseKey = [GTMBase64 decodeString:key]; // 將key 轉(zhuǎn)換成 byte數(shù)組 Byte *buf = (Byte *)[baseKey bytes];// 定義key iv byte數(shù)組 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;// 字符串長度比較長 返回值給大點(diǎn) 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];// 返回?cái)?shù)組長度 減去MD5加密的16 size_t returnLength = resultdata.length - 16; /// 定義 Byte decryptionByte[returnLength];for (int i = 0; i < returnLength; ++i) { decryptionByte[i] = resultByte[i+16]; }/// md5 校驗(yàn) // unsigned char digest[16]; // CC_MD5(decryptionByte,returnLength, digest); // NSData *md5data = [NSData dataWithBytes:digest length:16];// 進(jìn)行解密校檢 // Byte *md5bte= (Byte *)[md5data bytes];// for (int i = 0; i < 40; i++) { // // // if (md5bte[i] !=decryptionByte[i] ) { // // System.out.println(md5Hash[i] + "MD5校驗(yàn)錯(cuò)誤。" + temp[i]); // // throw new Exception("MD5校驗(yàn)錯(cuò)誤。"); // // 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;}項(xiàng)目中遇到的一些坑,在 DEMO 中都已經(jīng)注釋出來,寫的比較清楚,如果該 DEMO 幫助了您,也希望能給個(gè) star
鼓勵(lì)一下,如果在使用中您有任何問題,可以在 github issues,我會(huì)盡自己能力給您答復(fù) 。
在這里感謝這些 blog 的作者,讓我在開發(fā)過程中少走了很多彎路:[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)轉(zhuǎn)載于:https://www.cnblogs.com/feiyangkl/p/5985753.html
總結(jié)
- 上一篇: C++中的类加多线程代码修炼之二
- 下一篇: 物联网感知-基于分布式光纤传感的石油石化