先前一直在做安卓,最近要开发iPhone客户端,这其中遇到的最让人纠结的要属Java、Android和iPhone三个平台加解密不一致的问 题。因为手机端后台通常是用JAVA开发的Web Service,Android和iPhone客户端调用同样的Web Service接口,为了数据安全考虑,要对数据进行加密。头疼的问题就来了,很难编写出一套加密程序,在3个平台间加解密的结果一致,总不能为 Android和iPhone两个客户端各写一套Web Service接口吧?我相信还会有很多朋友为此困惑,在此分享一套3DES加密程序,能够实现Java、Android和iPhone三个平台加解密一 致。
首先是JAVA端的加密工具类,它同样适用于Android端,无需任何修改,即可保证Java与Android端的加解密一致,并且中文不会乱码。
class="dp-j" style="margin-left: 55px; padding-top: 5px; padding-bottom: 5px; color: #5c5c5c; border: none; margin-bottom: 1px !important; background-color: #f7f7f7;">
- package?org.liuyq.des3;??
- ????????
- import?java.security.Key;??
- ????????
- import?javax.crypto.Cipher;??
- import?javax.crypto.SecretKeyFactory;??
- import?javax.crypto.spec.DESedeKeySpec;??
- import?javax.crypto.spec.IvParameterSpec;??
- ????????
- ?
- ?
- ?
- ?
- ?
- ?
- public?class?Des3?{??
- ??????
- ?????private?final?static?String?secretKey?=?"liuyunqiang@lx100$#365#$"?;??
- ??????
- ?????private?final?static?String?iv?=?"01234567"?;??
- ??????
- ?????private?final?static?String?encoding?=?"utf-8"?;??
- ????????
- ??????
- ?
- ?
- ?
- ?
- ?
- ?
- ?????public?static?String?encode(String?plainText)?throws?Exception?{??
- ?????????Key?deskey?=?null?;??
- ?????????DESedeKeySpec?spec?=?new?DESedeKeySpec(secretKey.getBytes());??
- ?????????SecretKeyFactory?keyfactory?=?SecretKeyFactory.getInstance(?"desede"?);??
- ?????????deskey?=?keyfactory.generateSecret(spec);??
- ????????
- ?????????Cipher?cipher?=?Cipher.getInstance(?"desede/CBC/PKCS5Padding"?);??
- ?????????IvParameterSpec?ips?=?new?IvParameterSpec(iv.getBytes());??
- ?????????cipher.init(Cipher.ENCRYPT_MODE,?deskey,?ips);??
- ?????????byte?[]?encryptData?=?cipher.doFinal(plainText.getBytes(encoding));??
- ?????????return?Base64.encode(encryptData);??
- ?????}??
- ????????
- ??????
- ?
- ?
- ?
- ?
- ?
- ?
- ?????public?static?String?decode(String?encryptText)?throws?Exception?{??
- ?????????Key?deskey?=?null?;??
- ?????????DESedeKeySpec?spec?=?new?DESedeKeySpec(secretKey.getBytes());??
- ?????????SecretKeyFactory?keyfactory?=?SecretKeyFactory.getInstance(?"desede"?);??
- ?????????deskey?=?keyfactory.generateSecret(spec);??
- ?????????Cipher?cipher?=?Cipher.getInstance(?"desede/CBC/PKCS5Padding"?);??
- ?????????IvParameterSpec?ips?=?new?IvParameterSpec(iv.getBytes());??
- ?????????cipher.init(Cipher.DECRYPT_MODE,?deskey,?ips);??
- ????????
- ?????????byte?[]?decryptData?=?cipher.doFinal(Base64.decode(encryptText));??
- ????????
- ?????????return?new?String(decryptData,?encoding);??
- ?????}??
- }?
上面的加密工具类会使用到Base64这个类,该类的源代码如下:
- package?org.liuyq.des3;??
- import?java.io.ByteArrayOutputStream;??
- import?java.io.IOException;??
- import?java.io.OutputStream;??
- ????????
- ?
- ?
- ?
- ?
- ?
- ?
- public?class?Base64?{??
- ?????private?static?final?char?[]?legalChars?=?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"?.toCharArray();??
- ????????
- ?????public?static?String?encode(?byte?[]?data)?{??
- ?????????int?start?=?0?;??
- ?????????int?len?=?data.length;??
- ?????????StringBuffer?buf?=?new?StringBuffer(data.length?*?3?/?2?);??
- ????????
- ?????????int?end?=?len?-?3?;??
- ?????????int?i?=?start;??
- ?????????int?n?=?0?;??
- ????????
- ?????????while?(i?<=?end)?{??
- ?????????????int?d?=?((((?int?)?data[i])?&?0x0ff?)?<<?16?)?|?((((?int?)?data[i?+?1?])?&?0x0ff?)?<<?8?)?|?(((?int?)?data[i?+?2?])?&?0x0ff?);??
- ????????
- ?????????????buf.append(legalChars[(d?>>?18?)?&?63?]);??
- ?????????????buf.append(legalChars[(d?>>?12?)?&?63?]);??
- ?????????????buf.append(legalChars[(d?>>?6?)?&?63?]);??
- ?????????????buf.append(legalChars[d?&?63?]);??
- ????????
- ?????????????i?+=?3?;??
- ????????
- ?????????????if?(n++?>=?14?)?{??
- ?????????????????n?=?0?;??
- ?????????????????buf.append(?"?"?);??
- ?????????????}??
- ?????????}??
- ????????
- ?????????if?(i?==?start?+?len?-?2?)?{??
- ?????????????int?d?=?((((?int?)?data[i])?&?0x0ff?)?<<?16?)?|?((((?int?)?data[i?+?1?])?&?255?)?<<?8?);??
- ????????
- ?????????????buf.append(legalChars[(d?>>?18?)?&?63?]);??
- ?????????????buf.append(legalChars[(d?>>?12?)?&?63?]);??
- ?????????????buf.append(legalChars[(d?>>?6?)?&?63?]);??
- ?????????????buf.append(?"="?);??
- ?????????}?else?if?(i?==?start?+?len?-?1?)?{??
- ?????????????int?d?=?(((?int?)?data[i])?&?0x0ff?)?<<?16?;??
- ????????
- ?????????????buf.append(legalChars[(d?>>?18?)?&?63?]);??
- ?????????????buf.append(legalChars[(d?>>?12?)?&?63?]);??
- ?????????????buf.append(?"=="?);??
- ?????????}??
- ????????
- ?????????return?buf.toString();??
- ?????}??
- ????????
- ?????private?static?int?decode(?char?c)?{??
- ?????????if?(c?>=?'A'?&&?c?<=?'Z'?)??
- ?????????????return?((?int?)?c)?-?65?;??
- ?????????else?if?(c?>=?'a'?&&?c?<=?'z'?)??
- ?????????????return?((?int?)?c)?-?97?+?26?;??
- ?????????else?if?(c?>=?'0'?&&?c?<=?'9'?)??
- ?????????????return?((?int?)?c)?-?48?+?26?+?26?;??
- ?????????else?
- ?????????????switch?(c)?{??
- ?????????????case?'+'?:??
- ?????????????????return?62?;??
- ?????????????case?'/'?:??
- ?????????????????return?63?;??
- ?????????????case?'='?:??
- ?????????????????return?0?;??
- ?????????????default?:??
- ?????????????????throw?new?RuntimeException(?"unexpected?code:?"?+?c);??
- ?????????????}??
- ?????}??
- ????????
- ??????
- ?
- ?
- ????????
- ?????public?static?byte?[]?decode(String?s)?{??
- ????????
- ?????????ByteArrayOutputStream?bos?=?new?ByteArrayOutputStream();??
- ?????????try?{??
- ?????????????decode(s,?bos);??
- ?????????}?catch?(IOException?e)?{??
- ?????????????throw?new?RuntimeException();??
- ?????????}??
- ?????????byte?[]?decodedBytes?=?bos.toByteArray();??
- ?????????try?{??
- ?????????????bos.close();??
- ?????????????bos?=?null?;??
- ?????????}?catch?(IOException?ex)?{??
- ?????????????System.err.println(?"Error?while?decoding?BASE64:?"?+?ex.toString());??
- ?????????}??
- ?????????return?decodedBytes;??
- ?????}??
- ????????
- ?????private?static?void?decode(String?s,?OutputStream?os)?throws?IOException?{??
- ?????????int?i?=?0?;??
- ????????
- ?????????int?len?=?s.length();??
- ????????
- ?????????while?(?true?)?{??
- ?????????????while?(i?<?len?&&?s.charAt(i)?<=?'?'?)??
- ?????????????????i++;??
- ????????
- ?????????????if?(i?==?len)??
- ?????????????????break?;??
- ????????
- ?????????????int?tri?=?(decode(s.charAt(i))?<<?18?)?+?(decode(s.charAt(i?+?1?))?<<?12?)?+?(decode(s.charAt(i?+?2?))?<<?6?)?+?(decode(s.charAt(i?+?3?)));??
- ????????
- ?????????????os.write((tri?>>?16?)?&?255?);??
- ?????????????if?(s.charAt(i?+?2?)?==?'='?)??
- ?????????????????break?;??
- ?????????????os.write((tri?>>?8?)?&?255?);??
- ?????????????if?(s.charAt(i?+?3?)?==?'='?)??
- ?????????????????break?;??
- ?????????????os.write(tri?&?255?);??
- ????????
- ?????????????i?+=?4?;??
- ?????????}??
- ?????}??
- }?
?
接下来是iPhone端的加密程序,当然是用Ojbective-C写的3DES加密程序,源代码如下:?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ????????
- #import?<Foundation/Foundation.h>??
- ????????
- ????????
- @interface?DES3Util?:?NSObject?{??
- ????????
- }??
- ????????
- ?
- +?(NSString*)encrypt:(NSString*)plainText;??
- ????????
- ?
- +?(NSString*)decrypt:(NSString*)encryptText;??
- ????????
- @end?
?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ????????
- #import?"DES3Util.h"??
- #import?<CommonCrypto/CommonCryptor.h>??
- #import?"GTMBase64.h"??
- ????????
- #define?gkey????????????@"liuyunqiang@lx100$#365#$"??
- #define?gIv?????????????@"01234567"??
- ????????
- @implementation?DES3Util??
- ????????
- ?
- +?(NSString*)encrypt:(NSString*)plainText?{??
- ?????NSData*?data?=?[plainText?dataUsingEncoding:NSUTF8StringEncoding];??
- ?????size_t?plainTextBufferSize?=?[data?length];??
- ?????const?void?*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);??
- ????????????
- ?????const?void?*vkey?=?(const?void?*)?[gkey?UTF8String];??
- ?????const?void?*vinitVec?=?(const?void?*)?[gIv?UTF8String];??
- ????????????
- ?????ccStatus?=?CCCrypt(kCCEncrypt,??
- ????????????????????????kCCAlgorithm3DES,??
- ????????????????????????kCCOptionPKCS7Padding,??
- ????????????????????????vkey,??
- ????????????????????????kCCKeySize3DES,??
- ????????????????????????vinitVec,??
- ????????????????????????vplainText,??
- ????????????????????????plainTextBufferSize,??
- ????????????????????????(void?*)bufferPtr,??
- ????????????????????????bufferPtrSize,??
- ????????????????????????&movedBytes);??
- ????????????
- ?????NSData?*myData?=?[NSData?dataWithBytes:(const?void?*)bufferPtr?length:(NSUInteger)movedBytes];??
- ?????NSString?*result?=?[GTMBase64?stringByEncodingData:myData];??
- ?????return?result;??
- }??
- ????????
- ?
- +?(NSString*)decrypt:(NSString*)encryptText?{??
- ?????NSData?*encryptData?=?[GTMBase64?decodeData:[encryptText?dataUsingEncoding:NSUTF8StringEncoding]];??
- ?????size_t?plainTextBufferSize?=?[encryptData?length];??
- ?????const?void?*vplainText?=?[encryptData?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);??
- ????????????
- ?????const?void?*vkey?=?(const?void?*)?[gkey?UTF8String];??
- ?????const?void?*vinitVec?=?(const?void?*)?[gIv?UTF8String];??
- ????????????
- ?????ccStatus?=?CCCrypt(kCCDecrypt,??
- ????????????????????????kCCAlgorithm3DES,??
- ????????????????????????kCCOptionPKCS7Padding,??
- ????????????????????????vkey,??
- ????????????????????????kCCKeySize3DES,??
- ????????????????????????vinitVec,??
- ????????????????????????vplainText,??
- ????????????????????????plainTextBufferSize,??
- ????????????????????????(void?*)bufferPtr,??
- ????????????????????????bufferPtrSize,??
- ????????????????????????&movedBytes);??
- ????????????
- ?????NSString?*result?=?[[[NSString?alloc]?initWithData:[NSData?dataWithBytes:(const?void?*)bufferPtr???
- ?????????????????????????????????length:(NSUInteger)movedBytes]?encoding:NSUTF8StringEncoding]?autorelease];??
- ?????return?result;??
- }??
- ????????
- @end?
iPhone端的加密工具类中引入了“GTMBase64.h”,这是iOS平台的Base64编码工具类,见附件
好了,赶紧试一下吧,JAVA,Android和iPhone三个平台的加密不一致问题是不是解决了呢?以上为3DES加密,也可将其改为AES加密。 其实,对此问题,还有一种更好的实现方式,那就是用C语言写一套加密程序,这样在iOS平台是可以直接使用C程序的,而在Java和Android端通过 JNI去调用C语言编写的加密方法,这是不是就实现了3个平台调用同一套加密程序呢?