文档章节

Android、iPhone和Java三个平台一致的加密工具

科技创造
 科技创造
发布于 2014/12/19 10:31
字数 1421
阅读 223
收藏 9

移动开发中遇到的最让人纠结的要属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个平台调用同一套加密程序。 


本文转载自:http://jingyan.baidu.com/article/b2c186c8ccce70c46ef6ff99.html

共有 人打赏支持
科技创造
粉丝 36
博文 199
码字总数 174505
作品 0
徐汇
程序员
私信 提问
Android平台和java平台 DES加密解密互通程序及其不能互通的原因 .

网上的demo一搜一大堆,但是,基本上都是一知半解(包括我)。为什么呢?我在尝试分别在两个平台加密的时候,竟然发现Android DES 加密和java DES加密的程序不能互通。就是加密的结果不一样,...

鉴客
2011/12/26
8.7K
11
【北京】【猎头职位】某上市公司 招聘 高级开发工程师(C、C++),android,java,iphone

公司总部设于北京,下设上海、广州分公司,并在济南、武汉、成都、深圳、杭州等地设立了办事处。 职位名称:高级Java研发工程师 (12K~16K/月) 岗位职责: 参与分布式基础架构体系的开发工作...

leonrisfond
2011/10/31
620
8
Windows下部署Appium教程(Android App自动化测试框架搭建)

----------------------------------------------appium的一些基本概念---------------------------------------------- appium的核心其实是一个暴露了一系列REST API的server。 这个server的......

outcat
2015/08/12
0
26
两大开源游戏引擎Cocos2d-x及OGEngine对比分析

在近期的全球移动开发者大会上,触控发布了Cocos 3D引擎;而在差不多同时间,以安卓为主的OGEngine也发布了新版本,并宣布将支持跨平台。 Cocos2d-x和OGEngine都是当前比较受开发者欢迎的开源...

橙游OrangeGame
2014/08/11
11.1K
1
开源公司黄页之 Google 开源软件推荐

在企业使用开源和贡献开源方面,Google一直是行业的典范。一直以来,Google都在极力推广和倡导开源,并发布了一系列开源项目。如果没有开源软件,Google也难以达到今日的成功。开源中国社区目...

oschina
2016/07/08
10.6K
13

没有更多内容

加载失败,请刷新页面

加载更多

matlab-线性代数 齐次方程组 基础解系和通解

  matlab : R2018a 64bit     OS : Windows 10 x64 typesetting : Markdown    blog : my.oschina.net/zhichengjiu    gitee : gitee.com/zhichengjiu   code clearclc% x1+2*......

志成就
47分钟前
1
0
一线互联网技术推荐:Java工程师架构知识系统化汇总,面完45K!

根据高端招聘平台100 offer发布的Java人才盘点报告,在过去的2018年,Java仍然是最流行、招聘供需量最大的技术语言。 在此基础上,互联网行业针对 Java 开发的招聘需求,也是近年技术类岗位供...

java知识分子
53分钟前
6
0
JAVA并发编程JUC基础学习(简介)

之前写过一篇并发编程的简单实例应用,Future快速实现并发编程,可以很快的在自己的项目中应用,但并不系统,之前说过总结一篇(或者一系列)java.util.concurrent 这个并发编程工具类的学习...

小海bug
55分钟前
2
0
简单描述PHP发展历程

PHP简介 PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域...

问题终结者
今天
4
0
结构体指针需要初始化

过年过的大脑已经瓦特了。 #include <stdio.h>#define N 10#define MAXSIZE 100typedef struct {int r[MAXSIZE+1];/* 用于存储要排序数组 */ int length;/* 用于记录顺序表的...

niithub
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部