DES 加密 解密

EncryptUtil

feiyangklDES

一行代碼完成DES加密,加密模式 DES + CBChtml

DEMO GIF

DEMO 簡介

最近項目中用到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

DEMO 使用示例

//加密

/// 加密
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)
相關文章
相關標籤/搜索