代码加密

移动开发中遇到的最让人纠结的要属Java、Android和iPhone三个平台加解密不一致的问题。因为手机端后台通常是用JAVA开发的Web Service,Android和iPhone客户端调用同样的Web Service接口,为了数据安全考虑,要对数据进行加密。头疼的问题就来了,很难编写出一套加密程序,在3个平台间加解密的结果一致,总不能为Android和iPhone两个客户端各写一套Web Service接口吧?我相信还会有很多朋友为此困惑,在此分享一套3DES加密程序,能够实现Java、Android和iPhone三个平台加解密一致。 

        首先是JAVA端的加密工具类,它同样适用于Android端,无需任何修改,即可保证Java与Android端的加解密一致,并且中文不会乱码。 
Java代码

  1. package org.liuyq.des3;


  2. import java.security.Key;


  3. import javax.crypto.Cipher;

  4. import javax.crypto.SecretKeyFactory;

  5. import javax.crypto.spec.DESedeKeySpec;

  6. import javax.crypto.spec.IvParameterSpec;


  7. /**

  8. * 3DES加密工具类

  9. */

  10. public class Des3 {

  11.         // 密钥

  12.         private final static String secretKey = "liuyunqiang@lx100$#365#$";

  13.         // 向量

  14.         private final static String iv = "01234567";

  15.         // 加解密统一使用的编码方式

  16.         private final static String encoding = "utf-8";


  17.         /**

  18.          * 3DES加密

  19.          * 

  20.          * @param plainText 普通文本

  21.          * @return

  22.          * @throws Exception 

  23.          */

  24.         public static String encode(String plainText) throws Exception {

  25.                 Key deskey = null;

  26.                 DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());

  27.                 SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");

  28.                 deskey = keyfactory.generateSecret(spec);


  29.                 Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");

  30.                 IvParameterSpec ips = new IvParameterSpec(iv.getBytes());

  31.                 cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);

  32.                 byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding));

  33.                 return Base64.encode(encryptData);

  34.         }


  35.         /**

  36.          * 3DES解密

  37.          * 

  38.          * @param encryptText 加密文本

  39.          * @return

  40.          * @throws Exception

  41.          */

  42.         public static String decode(String encryptText) throws Exception {

  43.                 Key deskey = null;

  44.                 DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());

  45.                 SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");

  46.                 deskey = keyfactory.generateSecret(spec);

  47.                 Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");

  48.                 IvParameterSpec ips = new IvParameterSpec(iv.getBytes());

  49.                 cipher.init(Cipher.DECRYPT_MODE, deskey, ips);


  50.                 byte[] decryptData = cipher.doFinal(Base64.decode(encryptText));


  51.                 return new String(decryptData, encoding);

  52.         }

  53. }


复制代码

上面的加密工具类会使用到Base64这个类,该类的源代码如下: Java代码

  1. import java.io.ByteArrayOutputStream;

  2. import java.io.IOException;

  3. import java.io.OutputStream;


  4. /**

  5. * Base64编码工具类

  6. */

  7. public class Base64 {

  8.         private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();


  9.         public static String encode(byte[] data) {

  10.                 int start = 0;

  11.                 int len = data.length;

  12.                 StringBuffer buf = new StringBuffer(data.length * 3 / 2);


  13.                 int end = len - 3;

  14.                 int i = start;

  15.                 int n = 0;


  16.                 while (i <= end) {

  17.                         int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 0x0ff) << 8) | (((int) data[i + 2]) & 0x0ff);


  18.                         buf.append(legalChars[(d >> 18) & 63]);

  19.                         buf.append(legalChars[(d >> 12) & 63]);

  20.                         buf.append(legalChars[(d >> 6) & 63]);

  21.                         buf.append(legalChars[d & 63]);


  22.                         i += 3;


  23.                         if (n++ >= 14) {

  24.                                 n = 0;

  25.                                 buf.append(" ");

  26.                         }

  27.                 }


  28.                 if (i == start + len - 2) {

  29.                         int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 255) << 8);


  30.                         buf.append(legalChars[(d >> 18) & 63]);

  31.                         buf.append(legalChars[(d >> 12) & 63]);

  32.                         buf.append(legalChars[(d >> 6) & 63]);

  33.                         buf.append("=");

  34.                 } else if (i == start + len - 1) {

  35.                         int d = (((int) data[i]) & 0x0ff) << 16;


  36.                         buf.append(legalChars[(d >> 18) & 63]);

  37.                         buf.append(legalChars[(d >> 12) & 63]);

  38.                         buf.append("==");

  39.                 }


  40.                 return buf.toString();

  41.         }


  42.         private static int decode(char c) {

  43.                 if (c >= 'A' && c <= 'Z')

  44.                         return ((int) c) - 65;

  45.                 else if (c >= 'a' && c <= 'z')

  46.                         return ((int) c) - 97 + 26;

  47.                 else if (c >= '0' && c <= '9')

  48.                         return ((int) c) - 48 + 26 + 26;

  49.                 else

  50.                         switch (c) {

  51.                         case '+':

  52.                                 return 62;

  53.                         case '/':

  54.                                 return 63;

  55.                         case '=':

  56.                                 return 0;

  57.                         default:

  58.                                 throw new RuntimeException("unexpected code: " + c);

  59.                         }

  60.         }


  61.         /**

  62.          * Decodes the given Base64 encoded String to a new byte array. The byte array holding the decoded data is returned.

  63.          */


  64.         public static byte[] decode(String s) {


  65.                 ByteArrayOutputStream bos = new ByteArrayOutputStream();

  66.                 try {

  67.                         decode(s, bos);

  68.                 } catch (IOException e) {

  69.                         throw new RuntimeException();

  70.                 }

  71.                 byte[] decodedBytes = bos.toByteArray();

  72.                 try {

  73.                         bos.close();

  74.                         bos = null;

  75.                 } catch (IOException ex) {

  76.                         System.err.println("Error while decoding BASE64: " + ex.toString());

  77.                 }

  78.                 return decodedBytes;

  79.         }


  80.         private static void decode(String s, OutputStream os) throws IOException {

  81.                 int i = 0;


  82.                 int len = s.length();


  83.                 while (true) {

  84.                         while (i < len && s.charAt(i) <= ' ')

  85.                                 i++;


  86.                         if (i == len)

  87.                                 break;


  88.                         int tri = (decode(s.charAt(i)) << 18) + (decode(s.charAt(i + 1)) << 12) + (decode(s.charAt(i + 2)) << 6) + (decode(s.charAt(i + 3)));


  89.                         os.write((tri >> 16) & 255);

  90.                         if (s.charAt(i + 2) == '=')

  91.                                 break;

  92.                         os.write((tri >> 8) & 255);

  93.                         if (s.charAt(i + 3) == '=')

  94.                                 break;

  95.                         os.write(tri & 255);


  96.                         i += 4;

  97.                 }

  98.         }

  99. }


复制代码

接下来是iPhone端的加密程序,当然是用Ojbective-C写的3DES加密程序,源代码如下: 
Java代码

  1. //

  2. //  DES3Util.h

  3. //


  4. #import <Foundation/Foundation.h>



  5. @interface DES3Util : NSObject {


  6. }


  7. // 加密方法

  8. + (NSString*)encrypt:(NSString*)plainText;


  9. // 解密方法

  10. + (NSString*)decrypt:(NSString*)encryptText;


  11. @end


复制代码

Java代码

  1. //

  2. //  DES3Util.m

  3. //


  4. #import "DES3Util.h"

  5. #import <CommonCrypto/CommonCryptor.h>

  6. #import "GTMBase64.h"


  7. #define gkey                        @"liuyunqiang@lx100$#365#$"

  8. #define gIv             @"01234567"


  9. @implementation DES3Util


  10. // 加密方法

  11. + (NSString*)encrypt:(NSString*)plainText {

  12.     NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];

  13.         size_t plainTextBufferSize = [data length];

  14.         const void *vplainText = (const void *)[data bytes];

  15.     

  16.     CCCryptorStatus ccStatus;

  17.     uint8_t *bufferPtr = NULL;

  18.     size_t bufferPtrSize = 0;

  19.     size_t movedBytes = 0;

  20.     

  21.     bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);

  22.     bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));

  23.     memset((void *)bufferPtr, 0x0, bufferPtrSize);

  24.     

  25.     const void *vkey = (const void *) [gkey UTF8String];

  26.     const void *vinitVec = (const void *) [gIv UTF8String];

  27.     

  28.     ccStatus = CCCrypt(kCCEncrypt,

  29.                        kCCAlgorithm3DES,

  30.                        kCCOptionPKCS7Padding,

  31.                        vkey,

  32.                        kCCKeySize3DES,

  33.                        vinitVec,

  34.                        vplainText,

  35.                        plainTextBufferSize,

  36.                        (void *)bufferPtr,

  37.                        bufferPtrSize,

  38.                        &movedBytes);

  39.     

  40.     NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];

  41.         NSString *result = [GTMBase64 stringByEncodingData:myData];

  42.     return result;

  43. }


  44. // 解密方法

  45. + (NSString*)decrypt:(NSString*)encryptText {

  46.     NSData *encryptData = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];

  47.         size_t plainTextBufferSize = [encryptData length];

  48.         const void *vplainText = [encryptData bytes];

  49.     

  50.     CCCryptorStatus ccStatus;

  51.     uint8_t *bufferPtr = NULL;

  52.     size_t bufferPtrSize = 0;

  53.     size_t movedBytes = 0;

  54.     

  55.     bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);

  56.     bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));

  57.     memset((void *)bufferPtr, 0x0, bufferPtrSize);

  58.     

  59.     const void *vkey = (const void *) [gkey UTF8String];

  60.     const void *vinitVec = (const void *) [gIv UTF8String];

  61.     

  62.     ccStatus = CCCrypt(kCCDecrypt,

  63.                        kCCAlgorithm3DES,

  64.                        kCCOptionPKCS7Padding,

  65.                        vkey,

  66.                        kCCKeySize3DES,

  67.                        vinitVec,

  68.                        vplainText,

  69.                        plainTextBufferSize,

  70.                        (void *)bufferPtr,

  71.                        bufferPtrSize,

  72.                        &movedBytes);

  73.     

  74.     NSString *result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr 

  75.                                                                 length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding] autorelease];

  76.     return result;

  77. }


  78. @end


复制代码

iPhone端的加密工具类中引入了“GTMBase64.h”,这是iOS平台的Base64编码工具类,就不在这里贴出相关代码了,需要的百度一下就能找到。 

        这样,JAVA,Android和iPhone三个平台的加密不一致问题就可以解决了。其实,对此问题,还有一种更好的实现方式,那就是用C语言写一套加密程序,这样在iOS平台是可以直接使用C程序的,而在Java和Android端通过JNI去调用C语言编写的加密方法,这样也可以实现3个平台调用同一套加密程序。 


上一篇:CentOS 7.0 使用 yum 安装 MariaDB 与 MariaDB 的简单配置


下一篇:CSS应用给网页元素的几种方式总结