精华内容
下载资源
问答
  • Androidhttp请求加密机制详解

    万次阅读 2016-11-09 11:59:33
    Android开发中,难免会遇到需要加解密一些数据内容存到本地文件、或者通过网络传输到其他服务器和设备的问题,但并不是使用了加密就绝对安全了,如果加密函数使用不正确,加密数据很容易受到逆向破解攻击。...

    Android开发中,难免会遇到需要加解密一些数据内容存到本地文件、或者通过网络传输到其他服务器和设备的问题,但并不是使用了加密就绝对安全了,如果加密函数使用不正确,加密数据很容易受到逆向破解攻击。还有很多开发者没有意识到的加密算法的问题。

    1、需要了解的基本概念
     

    密码学的三大作用:加密( Encryption)、认证(Authentication),鉴定(Identification) 
    加密:防止坏人获取你的数据。 
    鉴权:防止坏人假冒你的身份。
    明文、密文、密钥、对称加密算法、非对称加密算法,这些基本概念和加密算法原理就不展开叙述了。

    认证:防止坏人修改了你的数据而你却并没有发现。 




     Base64编码算法
     
    Base64编码算法是一种用64个字符(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/)来表示任意二进制数据的方法。在计算机网络发展的早期,由于“历史原因”,电子邮件不支持非ASCII码字符,如果要传送的电子邮件带有非ASCII码字符(诸如中文)或者图片,用户收到的电子邮件将会是一堆乱码,因此发明了Base64编码算法。至于为何会乱码?请大家自行Google。在加解密算法中,原始的数据和加密后的数据一般也是二进制数据,为了不传输出错,方便保存或者调试代码,一般需要对加密后的数据进行base64编码。 
    Android提供了Base64编码的工具类android.util.Base64,可以直接使用,不用自己去实现base64编码的算法了。 如:
    开发者建议: base64只是一种编码方式,并不是一种加密算法,不要使用base64来加密数据。
    消息认证算法
     
    要确保加密的消息不是别人伪造的,需要提供一个消息认证码(MAC,Message authentication code)。 
    消息认证码是带密钥的hash函数,基于密钥和hash函数。
    密钥双方事先约定,不能让第三方知道。
    消息发送者使用MAC算法计算出消息的MAC值,追加到消息后面一起发送给接收者。 
    接收者收到消息后,用相同的MAC算法计算接收到消息MAC值,并与接收到的MAC值对比是否一样。 
     
    开发者建议: 
    建议使用HMAC-SHA256算法,避免使用CBC-MAC。 
    HMAC-SHA256例子如下:
    对称加密算法
     

    在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。 

    该算法的缺点是,如果一旦密钥泄漏,那么加密的内容将都不可信了。
     
    随着Internet网的广泛应用,信息安全问题日益突出,以数据加密技术为核心的信息安全技术也得到了极大的发展。目前的数据加密技术根据加密密钥类型可分私钥加密(对称加密)系统和公钥加密(非对称加密)系统。
    AES算法
    AES基本原理及算法流程

    AES类型 密钥长度 分组长度 加密轮数
    AES-128 4字 4字 10
    AES-192 6字 4字 12
    AES-256 8字 4字 14
    A E I M
    B F J N
    C G K O
    D H L P

    这个多项式与x4+1互质,因此是可逆的。列混合变换的算术表达式为:s’(x)= a(x) s(x),其中, s(x)表示状态的列多项式。
    • 4、轮密钥的添加变换AddRoundKey() 
     在这个操作中,轮密钥被简单地异或到状态中,轮密钥根据密钥表获得,其长度等于数据块的长度Nb。
    AES算法流程
    对于发送方,它首先创建一个AES私钥,并用口令对这个私钥进行加密。然后把用口令加密后的AES密钥通过Internet发送到接收方。发送方解密这个私钥,并用此私钥加密明文得到密文,密文和加密后的AES密钥一起通过Internet发送到接收方。接收方收到后再用口令对加密密钥进行解密得到AES密钥,最后用解密后的密钥把收到的密文解密成明文。图7中是这个过程的实现流程。
    • 图7 AES算法流程

    对称加密算法是较传统的加密体制,通信双方在加/解密过程中使用他们共享的单一密钥,鉴于其算法简单和加密速度快的优点,目前仍然是主流的密码体制之一。最常用的对称密码算法是数据加密标准(DES)算法,但是由于DES密钥长度较短,已经不适合当今分布式开放网络对数据加密安全性的要求。最后,一种新的基于Rijndael算法对称高级数据加密标准AES取代了数据加密标准DES。非对称加密由于加/解密钥不同(公钥加密,私钥解密),密钥管理简单,也得到广泛应用。

    美国国家标准和技术研究所(NIST)经过三轮候选算法筛选,从众多的分组密码中选中Rijndael算法作为高级加密标准(AES)。Rijndael密码是一个迭代型分组密码,分组长度和密码长度都是可变的,分组长度和密码长度可以独立的指定为128比特,192比特或者256比特。AES的加密算法的数据处理单位是字节,128位的比特信息被分成16个字节,按顺序复制到一个4*4的矩阵中,称为状态(state),AES的所有变换都是基于状态矩阵的变换。

    用Nr表示对一个数据分组加密的轮数(加密轮数与密钥长度的关系如表1所示)。在轮函数的每一轮迭代中,包括四步变换,分别是字节代换运算(ByteSub())、行变换(ShiftRows())、列混合(MixColumns())以及轮密钥的添加变换AddRoundKey()[3],其作用就是通过重复简单的非线形变换、混合函数变换,将字节代换运算产生的非线性扩散,达到充分的混合,在每轮迭代中引入不同的密钥,从而实现加密的有效性。

    表1 是三种不同类型的AES加密密钥分组大小与相应的加密轮数的对照表。加密开始时,输入分组的各字节按表2 的方式装入矩阵state中。如输入ABCDEFGHIJKLMNOP,则输入块影射到如表2的状态矩阵中。

    表1:

    AES类型 密钥长度 分组长度 加密轮数
    AES-128 4字 4字 10
    AES-192 6字 4字 12
    AES-256 8字 4字 14

    表2:

    AEIM

    BFJN

    CGKO

    DHLP

    • 1、字节代换运算(ByteSub())

      字节代换运算是一个可逆的非线形字节代换操作,对分组中的每个字节进行,对字节的操作遵循一个代换表,即S盒。S盒由有限域 GF(28)上的乘法取逆和GF(2)上的仿射变换两步组成。

    • 2、行变换ShiftRows()

      行变换是一种线性变换,其目的就是使密码信息达到充分的混乱,提高非线形度。行变换对状态的每行以字节为单位进行循环右移,移动字节数根据行数来确定,第0行不发生偏移,第一行循环右移一个字节,第二行移两个,依次类推。

    +3、 列混合变换MixColumns()

    列变换就是从状态中取出一列,表示成多项式的形式后,用它乘以一个固定的多项式a(x),然后将所得结果进行取模运算,模值为 x4+1。其中a(x)={03}x3+{02}x2+{01}x+{02}, 

    AES算法流程


    开发者建议: 
    1、建议使用AES算法。 
    2、DES默认的是56位的加密密钥,已经不安全,不建议使用
    3Android 提供的AES加密算法API默认使用的是ECB模式,所以要显式指定加密算法为:CBC或CFB模式,可带上PKCS5Padding填充。AES密钥长度最少是128位,推荐使用256位。

    非对称加密
     
    非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密(这个过程可以做数字签名)。 
    非对称加密主要使用的是RSA算法。
     

    RSA算法
    RSA算法基本原理及流程

    RSA是在1977年发明RSA密码系统的三个人的名字的首字母的缩写,他们是:Ron Rivest、Adi Shamir和Leonard Adleman。它是第一个公钥加密算法,在很多密码协议中都有应用,如SSL和S/MIME。RSA算法是基于大质数的因数分解的公匙体系。简单的讲,就是两个很大的质数,一个作为公钥,另一个作为私钥,如用其中一个加密,则用另一个解密。密钥长度从40到2048位可变,密钥越长,加密效果越好,但加密解密的开销也大。RSA算法可简单描述如下:

    公开密钥:n=pq,(p,q为两个不同的很大的质数,p和q必须保密)
    将(p-1)和(q-1)相乘得到φ(n)
    选择一个整数e (1<e<φ(n))与φ(n)互质
    秘密密钥:d=e-1modφ(n),即计算一个数字d,使得它满足公式 de=1 modφ(n)
    加密:c=mc(mod n) 
    解密:m=cd(mod n),m为明文,c为密文。
    

    RSA算法实现流程

    首先,接收方创建RSA密匙对,即一个公钥和一个私钥,公钥被发送到发送方,私钥则被保存在接收方。发送方在接收到这个公钥后,用该公钥对明文进行加密得到密文,然后把密文通过网络传输给接收方。接收方在收到它们后,用RSA私钥对收到的密文进行解密,最后得到明文。图8是整个过程的实现流程。

    • 图8 RSA算法实现流程

    这里写图片描述

    开发者建议: 
    1、注意密钥长度不要低于512位,建议使用2048位的密钥长度。 
    使用RSA进行数字签名的算法,如:
    2、使用RSA算法做加密,RSA加密算法应使用Cipher.getInstance(RSA/ECB/OAEPWithSHA256AndMGF1Padding),否则会存在重放攻击的风险。 如:
     
    2.8 加密算法PBE
     
    PBE是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。 
    开发者建议: 
    使用基于口令的加密算法PBE时,生成密钥时要加盐,盐的取值最好来自SecureRandom,并指定迭代次数。 如:
    (以上所有示例算法仅供参考)

    AES与RSA相结合数据加密方案

    RSA算法是公开密钥系统的代表,其安全性建立在具有大素数因子的合数,其因子分解困难这一法则之上的。Rijndael算法作为新一代的高级加密标准,运行时不需要计算机有非常高的处理能力和大的内存,操作可以很容易的抵御时间和空间的攻击,在不同的运行环境下始终能保持良好的性能。这使AES将安全,高效,性能,方便,灵活性集于一体,理应成为网络数据加密的首选。相比较,因为AES密钥的长度最长只有256比特,可以利用软件和硬件实现高速处理,而RSA算法需要进行大整数的乘幂和求模等多倍字长处理,处理速度明显慢于AES[5];所以AES算法加解密处理效率明显高于RSA算法。在密钥管理方面,因为AES算法要求在通信前对密钥进行秘密分配,解密的私钥必须通过网络传送至加密数据接收方,而RSA采用公钥加密,私钥解密(或私钥加密,公钥解密),加解密过程中不必网络传输保密的密钥;所以RSA算法密钥管理要明显优于AES算法。

    从上面比较得知,由于RSA加解密速度慢,不适合大量数据文件加密,因此在网络中完全用公开密码体制传输机密信息是没有必要,也是不太现实的。AES加密速度很快,但是在网络传输过程中如何安全管理AES密钥是保证AES加密安全的重要环节。这样在传送机密信息的双方,如果使用AES对称密码体制对传输数据加密,同时使用RSA不对称密码体制来传送AES的密钥,就可以综合发挥AES和RSA的优点同时避免它们缺点来实现一种新的数据加密方案。加解密实现流程如图(9)。

    • 图9 AES与RSA相结合数据加密方案流程 
      这里写图片描述

    具体过程是先由接收方创建RSA密钥对,接收方通过Internet发送RSA公钥到发送方,同时保存RSA私钥。而发送方创建AES密钥,并用该AES密钥加密待传送的明文数据,同时用接受的RSA公钥加密AES密钥,最后把用RSA公钥加密后的AES密钥同密文一起通过Internet传输发送到接收方。当接收方收到这个被加密的AES密钥和密文后,首先调用接收方保存的RSA私钥,并用该私钥解密加密的AES密钥,得到AES密钥。最后用该AES密钥解密密文得到明文。

    Android端 AES+RSA结合实践

    基本要求

    1. 保证传输数据的安全性
    2. 保证数据的完整性
    3. 能够验证客户端的身份

    基本流程

    Android端

    1. 服务器端(server)分别生成自己的RSA密钥对,并提供接口给Android客户端获取RSA公钥(rsaPublicKey)
    2. client生成AES密钥(aesKey)
    3. client使用自己的AES密钥(aesKey)对转换为json格式的请求明文数据(data)进行加密,得到加密后的请求数据encryptData
    4. client提供server提供的接口获取RSA公钥(rsaPublicKey)
    5. client使用获取RSA公钥(rsaPublicKey)对AES密钥(aesKey)进行加密,得到encryptAesKey
    6. client将encryptAesKey作为http请求头参数,将加密后的请求数据encryptData作为请求体一起传输给服务器端

    服务器端

    1. server响应client的http请求,读取http请求头。获得client传过来的加密后的AES密钥(encryptAesKey),读取http请求体,获得client传过来的加密后的请求数据(encryptData)。
    2. server使用自己的RSA私钥(rsaPrivateKey)对加密后的AES密钥(encryptAesKey)进行RSA解密,得到AES密钥(aesKey)
    3. 使用解密后的AES密钥(aesKey)对加密后的请求数据(encryptData),进行AES解密操作,得到解密后的请求数据(data),该数据为json格式
    4. 对解密后的请求数据(data)进行json解析,然后做相关的响应操作。

    基本上如下图所示的流程:

    这里写图片描述

    更多参考

    总结
     
    几条原则: 
    1、不要自己设计加密算法和协议,使用业界标准的算法。 
    2、对称加密算法不要使用ECB模式,不建议使用DES算法。 
    3、要选择合适长度的密钥。 
    4、要确保随机数生成器的种子具有足够的信息熵。 
    5、不要使用没有消息认证的加密算法加密消息,无法防重放。 
    6、当多个字符串拼接后做hash,要非常当心。 
    7、当给算法加yan盐取值时不要太短,不要重复。 
    8、使用初始化向量时IV时,IV为常量的CBC,CFB,GCM等和ECB一样可以重放,即采用上一个消息的最后一块密文作为下一个消息的IV,是不安全的。 
    9、密钥应遵循的原则 
    (1)密钥不能为常量,应随机,定期更换,如果加密数据时使用的密钥为常量,则相同明文加密会得到相同的密文,很难防止字典攻击。 
    (2)开发同学要防范密钥硬编码的毛病。 
    而在实际开发中,密钥如何保存始终是绕不过的坎?如果硬编码在代码中容易被逆向,如果放在设备的某个文件,也会被有经验的破解者逆向找到,在这里推荐阿里聚安全的安全组件服务,其中的安全加密功能提供了开发者密钥的安全管理与加密算法实现,保证密钥的安全性,实现安全的加解密操作。


    展开全文
  • 安卓版本9.0上app访问后台服务器一直报网络异常,无法访问后台数据。 解决办法 1.APP改用https请求 2.targetSdkVersion 降到27以下 3.配置文件解决网络请求 在 res 下新增一个 xml 目录,然后创建一个名为:...

    参考资源:https://www.cnblogs.com/renhui/p/9921790.html

    背景

    在安卓版本9.0上app访问后台服务器一直报网络异常,无法访问后台数据。

    解决办法

    1.APP改用https请求

    2.targetSdkVersion 降到27以下

    3.配置文件解决网络请求

    在 res 下新增一个 xml 目录,然后创建一个名为:network_security_config.xml 文件(名字自定) ,内容如下,大概意思就是允许开启http请求:

    <?xml version="1.0" encoding="utf-8"?>
    	<network-security-config>
    	<base-config cleartextTrafficPermitted="true" />
    </network-security-config>
    

    然后在APP的AndroidManifest.xml文件下的application标签增加以下属性

    <application
    	...
     android:networkSecurityConfig="@xml/network_security_config"
    ...
    />
    

    总结

    时刻记录遇到的奇异bug,保持旺盛的求知欲,茂密的头发即将离我远去。
    另:若有更好的解决办法或者解决办法无效,望告知,多谢,作揖。

    展开全文
  • Android 网络请求加密

    千次阅读 2016-04-01 17:04:59
    转载请注明出处: ...本文以Android客户端加密提交数据到Java服务端后进行解密为例子。 生成RSA公钥和密钥的方法请参考: http://blog.csdn.net/aa464971/article/details/51035200 Andro

    转载请注明出处:

    http://blog.csdn.net/aa464971/article/details/51034462


    本文以Android客户端加密提交数据到Java服务端后进行解密为例子。


    生成RSA公钥和密钥的方法请参考:

    http://blog.csdn.net/aa464971/article/details/51035200


    Android端的加密思路需要4步:

    1.生成AES密钥;

    2.使用RSA公钥加密刚刚生成的AES密钥;

    3.再使用第1步生成的AES密钥,通过AES加密需要提交给服务端的数据;

    4.将第2与第3生成的内容传给服务端。


    JAVA服务端的解密思路只需3步:

    1.获取到客户端传过来的AES密钥密文和内容密文;

    2.使用RSA私钥解密从客户端拿到的AES密钥密文;

    3.再使用第2步解密出来的明文密钥,通过AES解密内容的密文。


    AES的代码可以在JAVA和Android上通用

    1. package com.dyhdyh.encrypt;  
    2.   
    3. import java.io.UnsupportedEncodingException;  
    4. import java.security.NoSuchAlgorithmException;  
    5. import java.security.SecureRandom;  
    6.   
    7. import javax.crypto.Cipher;  
    8. import javax.crypto.KeyGenerator;  
    9. import javax.crypto.SecretKey;  
    10. import javax.crypto.spec.SecretKeySpec;  
    11.   
    12. /** 
    13.  * AES 
    14.  * @author dengyuhan 
    15.  * @create 2016/3/31 15:43 
    16.  */  
    17. public class AES {  
    18.     // /** 算法/模式/填充 **/  
    19.     private static final String CipherMode = "AES/ECB/PKCS5Padding";  
    20.     // private static final String CipherMode = "AES";  
    21.   
    22.     /** 
    23.      * 生成一个AES密钥对象 
    24.      * @return 
    25.      */  
    26.     public static SecretKeySpec generateKey(){  
    27.         try {  
    28.             KeyGenerator kgen = KeyGenerator.getInstance("AES");  
    29.             kgen.init(128new SecureRandom());    
    30.             SecretKey secretKey = kgen.generateKey();    
    31.             byte[] enCodeFormat = secretKey.getEncoded();    
    32.             SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");  
    33.             return key;  
    34.         } catch (NoSuchAlgorithmException e) {  
    35.             e.printStackTrace();  
    36.         }  
    37.         return null;  
    38.     }  
    39.   
    40.     /** 
    41.      * 生成一个AES密钥字符串 
    42.      * @return 
    43.      */  
    44.     public static String generateKeyString(){  
    45.         return byte2hex(generateKey().getEncoded());  
    46.     }  
    47.   
    48.     /** 
    49.      * 加密字节数据 
    50.      * @param content 
    51.      * @param key 
    52.      * @return 
    53.      */  
    54.     public static byte[] encrypt(byte[] content,byte[] key) {  
    55.         try {  
    56.             Cipher cipher = Cipher.getInstance(CipherMode);  
    57.             cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));  
    58.             byte[] result = cipher.doFinal(content);  
    59.             return result;  
    60.         } catch (Exception e) {  
    61.             e.printStackTrace();  
    62.         }  
    63.         return null;  
    64.     }  
    65.   
    66.     /** 
    67.      * 通过byte[]类型的密钥加密String 
    68.      * @param content 
    69.      * @param key 
    70.      * @return 16进制密文字符串 
    71.      */  
    72.     public static String encrypt(String content,byte[] key) {  
    73.         try {  
    74.             Cipher cipher = Cipher.getInstance(CipherMode);  
    75.             cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));  
    76.             byte[] data = cipher.doFinal(content.getBytes("UTF-8"));  
    77.             String result = byte2hex(data);  
    78.             return result;  
    79.         } catch (Exception e) {  
    80.             e.printStackTrace();  
    81.         }  
    82.         return null;  
    83.     }  
    84.   
    85.     /** 
    86.      * 通过String类型的密钥加密String 
    87.      * @param content 
    88.      * @param key 
    89.      * @return 16进制密文字符串 
    90.      */  
    91.     public static String encrypt(String content,String key) {  
    92.         byte[] data = null;  
    93.         try {  
    94.             data = content.getBytes("UTF-8");  
    95.         } catch (Exception e) {  
    96.             e.printStackTrace();  
    97.         }  
    98.         data = encrypt(data,new SecretKeySpec(hex2byte(key), "AES").getEncoded());  
    99.         String result = byte2hex(data);  
    100.         return result;  
    101.     }  
    102.   
    103.     /** 
    104.      * 通过byte[]类型的密钥解密byte[] 
    105.      * @param content 
    106.      * @param key 
    107.      * @return 
    108.      */  
    109.     public static byte[] decrypt(byte[] content,byte[] key) {  
    110.         try {  
    111.             Cipher cipher = Cipher.getInstance(CipherMode);  
    112.             cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));  
    113.             byte[] result = cipher.doFinal(content);  
    114.             return result;  
    115.         } catch (Exception e) {  
    116.             e.printStackTrace();  
    117.         }  
    118.         return null;  
    119.     }  
    120.   
    121.     /** 
    122.      * 通过String类型的密钥 解密String类型的密文 
    123.      * @param content 
    124.      * @param key 
    125.      * @return 
    126.      */  
    127.     public static String decrypt(String content, String key) {  
    128.         byte[] data = null;  
    129.         try {  
    130.             data = hex2byte(content);  
    131.         } catch (Exception e) {  
    132.             e.printStackTrace();  
    133.         }  
    134.         data = decrypt(data, hex2byte(key));  
    135.         if (data == null)  
    136.             return null;  
    137.         String result = null;  
    138.         try {  
    139.             result = new String(data, "UTF-8");  
    140.         } catch (UnsupportedEncodingException e) {  
    141.             e.printStackTrace();  
    142.         }  
    143.         return result;  
    144.     }  
    145.   
    146.     /** 
    147.      * 通过byte[]类型的密钥 解密String类型的密文 
    148.      * @param content 
    149.      * @param key 
    150.      * @return 
    151.      */  
    152.     public static String decrypt(String content,byte[] key) {  
    153.         try {  
    154.             Cipher cipher = Cipher.getInstance(CipherMode);  
    155.             cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(key, "AES"));  
    156.             byte[] data = cipher.doFinal(hex2byte(content));  
    157.             return new String(data, "UTF-8");  
    158.         } catch (Exception e) {  
    159.             e.printStackTrace();  
    160.         }  
    161.         return null;  
    162.     }  
    163.   
    164.     /** 
    165.      * 字节数组转成16进制字符串 
    166.      * @param b 
    167.      * @return 
    168.      */  
    169.     public static String byte2hex(byte[] b) { // 一个字节的数,  
    170.         StringBuffer sb = new StringBuffer(b.length * 2);  
    171.         String tmp = "";  
    172.         for (int n = 0; n < b.length; n++) {  
    173.             // 整数转成十六进制表示  
    174.             tmp = (Integer.toHexString(b[n] & 0XFF));  
    175.             if (tmp.length() == 1) {  
    176.                 sb.append("0");  
    177.             }  
    178.             sb.append(tmp);  
    179.         }  
    180.         return sb.toString().toUpperCase(); // 转成大写  
    181.     }  
    182.   
    183.     /** 
    184.      * 将hex字符串转换成字节数组 
    185.      * @param inputString 
    186.      * @return 
    187.      */  
    188.     private static byte[] hex2byte(String inputString) {  
    189.         if (inputString == null || inputString.length() < 2) {  
    190.             return new byte[0];  
    191.         }  
    192.         inputString = inputString.toLowerCase();  
    193.         int l = inputString.length() / 2;  
    194.         byte[] result = new byte[l];  
    195.         for (int i = 0; i < l; ++i) {  
    196.             String tmp = inputString.substring(2 * i, 2 * i + 2);  
    197.             result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);  
    198.         }  
    199.         return result;  
    200.     }  
    201. }  


    Android - RSA实现

    1. package com.dyhdyh.encrypt;  
    2.   
    3. import android.util.Base64;  
    4.   
    5. import java.io.BufferedReader;  
    6. import java.io.IOException;  
    7. import java.io.InputStream;  
    8. import java.io.InputStreamReader;  
    9. import java.security.KeyFactory;  
    10. import java.security.NoSuchAlgorithmException;  
    11. import java.security.interfaces.RSAPrivateKey;  
    12. import java.security.interfaces.RSAPublicKey;  
    13. import java.security.spec.InvalidKeySpecException;  
    14. import java.security.spec.PKCS8EncodedKeySpec;  
    15. import java.security.spec.X509EncodedKeySpec;  
    16.   
    17. import javax.crypto.Cipher;  
    18.   
    19. /** 
    20.  * 用于Android平台的RSA加密解密 
    21.  *  
    22.  * @desc 
    23.  * @author dengyuhan 
    24.  * @create 2016-3-31 下午2:36:18 
    25.  */  
    26. public class RSA {  
    27.     private static final String ALGORITHM = "RSA";  
    28.     private static final String TRANSFORMATION = "RSA";  
    29.   
    30.     /** 
    31.      * 从文件中输入流中加载公钥 
    32.      *  
    33.      * @param in 
    34.      *            公钥输入流 
    35.      * @throws Exception 
    36.      *             加载公钥时产生的异常 
    37.      */  
    38.     public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {  
    39.         try {  
    40.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
    41.             String readLine = null;  
    42.             StringBuilder sb = new StringBuilder();  
    43.             while ((readLine = br.readLine()) != null) {  
    44.                 if (readLine.charAt(0) == '-') {  
    45.                     continue;  
    46.                 } else {  
    47.                     sb.append(readLine);  
    48.                     sb.append('\r');  
    49.                 }  
    50.             }  
    51.             return loadPublicKey(sb.toString());  
    52.         } catch (IOException e) {  
    53.             throw new Exception("公钥数据流读取错误");  
    54.         } catch (NullPointerException e) {  
    55.             throw new Exception("公钥输入流为空");  
    56.         }  
    57.     }  
    58.   
    59.     /** 
    60.      * 从字符串中加载公钥 
    61.      *  
    62.      * @param publicKeyStr 
    63.      *            公钥数据字符串 
    64.      * @return 
    65.      * @throws Exception 
    66.      *             加载公钥时产生的异常 
    67.      */  
    68.     public static RSAPublicKey loadPublicKey(String publicKeyStr)  
    69.             throws Exception {  
    70.         try {  
    71.             byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);  
    72.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
    73.             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);  
    74.             return (RSAPublicKey) keyFactory.generatePublic(keySpec);  
    75.         } catch (NoSuchAlgorithmException e) {  
    76.             throw new Exception("无此算法");  
    77.         } catch (InvalidKeySpecException e) {  
    78.             throw new Exception("公钥非法");  
    79.         }catch (NullPointerException e) {  
    80.             throw new Exception("公钥数据为空");  
    81.         }  
    82.     }  
    83.   
    84.     /** 
    85.      * 从文件中加载私钥 
    86.      *  
    87.      * @param in 
    88.      *            私钥输入流 
    89.      * @return 
    90.      * @throws Exception 
    91.      */  
    92.     public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {  
    93.         try {  
    94.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
    95.             String readLine = null;  
    96.             StringBuilder sb = new StringBuilder();  
    97.             while ((readLine = br.readLine()) != null) {  
    98.                 if (readLine.charAt(0) == '-') {  
    99.                     continue;  
    100.                 } else {  
    101.                     sb.append(readLine);  
    102.                     sb.append('\r');  
    103.                 }  
    104.             }  
    105.             return loadPrivateKey(sb.toString());  
    106.         } catch (IOException e) {  
    107.             throw new Exception("私钥数据读取错误");  
    108.         } catch (NullPointerException e) {  
    109.             throw new Exception("私钥输入流为空");  
    110.         }  
    111.     }  
    112.   
    113.     /** 
    114.      * 从字符串中加载私钥 
    115.      *  
    116.      * @desc 
    117.      * @param privateKeyStr 
    118.      *            私钥字符串 
    119.      * @return 
    120.      * @throws Exception 
    121.      */  
    122.     public static RSAPrivateKey loadPrivateKey(String privateKeyStr)  
    123.             throws Exception {  
    124.         try {  
    125.             byte[] buffer = Base64.decode(privateKeyStr, Base64.DEFAULT);  
    126.             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);  
    127.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
    128.             return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);  
    129.         } catch (NoSuchAlgorithmException e) {  
    130.             throw new Exception("无此算法");  
    131.         } catch (InvalidKeySpecException e) {  
    132.             throw new Exception("私钥非法");  
    133.         }catch (NullPointerException e) {  
    134.             throw new Exception("私钥数据为空");  
    135.         }  
    136.     }  
    137.   
    138.     /** 
    139.      * 公钥加密 
    140.      *  
    141.      * @param data 
    142.      * @param publicKey 
    143.      * @return 
    144.      * @throws Exception 
    145.      */  
    146.     public static String encryptByPublicKey(String data, RSAPublicKey publicKey)  
    147.             throws Exception {  
    148.         // 模长  
    149.         int key_len = publicKey.getModulus().bitLength() / 8;  
    150.         // 加密数据长度 <= 模长-11  
    151.         String[] datas = splitString(data, key_len - 11);  
    152.         String mi = "";  
    153.         // 如果明文长度大于模长-11则要分组加密  
    154.         for (String s : datas) {  
    155.             mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));  
    156.         }  
    157.         return mi;  
    158.     }  
    159.   
    160.     /** 
    161.      * 公钥加密 
    162.      * @desc  
    163.      * @param data 
    164.      * @param publicKey 
    165.      * @return 
    166.      * @throws Exception 
    167.      */  
    168.     public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)  
    169.             throws Exception {  
    170.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
    171.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
    172.         return cipher.doFinal(data);  
    173.     }  
    174.   
    175.     /** 
    176.      * 私钥加密 
    177.      * @desc  
    178.      * @param data 
    179.      * @param privateKey 
    180.      * @return 
    181.      * @throws Exception 
    182.      */  
    183.     public static byte[] encryptByPrivateKey(byte[] data,  
    184.             RSAPrivateKey privateKey) throws Exception {  
    185.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
    186.         cipher.init(Cipher.ENCRYPT_MODE, privateKey);  
    187.         return cipher.doFinal(data);  
    188.     }  
    189.   
    190.   
    191.     /** 
    192.      * 私钥加密 
    193.      * @desc  
    194.      * @param data 
    195.      * @param privateKey 
    196.      * @return 
    197.      * @throws Exception 
    198.      */  
    199.     public static String encryptByPrivateKey(String data,  
    200.             RSAPrivateKey privateKey) throws Exception {  
    201.         // 模长  
    202.         int key_len = privateKey.getModulus().bitLength() / 8;  
    203.         // 加密数据长度 <= 模长-11  
    204.         String[] datas = splitString(data, key_len - 11);  
    205.         String mi = "";  
    206.         // 如果明文长度大于模长-11则要分组加密  
    207.         for (String s : datas) {  
    208.             mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));  
    209.         }  
    210.         return mi;  
    211.     }  
    212.   
    213.     /** 
    214.      * 私钥解密 
    215.      *  
    216.      * @param data 
    217.      * @param privateKey 
    218.      * @return 
    219.      * @throws Exception 
    220.      */  
    221.     public static String decryptByPrivateKey(String data,  
    222.             RSAPrivateKey privateKey) throws Exception {  
    223.         // 模长  
    224.         int key_len = privateKey.getModulus().bitLength() / 8;  
    225.         byte[] bytes = data.getBytes();  
    226.         byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
    227.         // 如果密文长度大于模长则要分组解密  
    228.         String ming = "";  
    229.         byte[][] arrays = splitArray(bcd, key_len);  
    230.         for (byte[] arr : arrays) {  
    231.             ming += new String(decryptByPrivateKey(arr, privateKey));  
    232.         }  
    233.         return ming;  
    234.     }  
    235.       
    236.     /** 
    237.      * 私钥解密 
    238.      * @desc  
    239.      * @param data 
    240.      * @param privateKey 
    241.      * @return 
    242.      * @throws Exception 
    243.      */  
    244.     public static byte[] decryptByPrivateKey(byte[] data,  
    245.             RSAPrivateKey privateKey) throws Exception {  
    246.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
    247.         cipher.init(Cipher.DECRYPT_MODE, privateKey);  
    248.         return cipher.doFinal(data);  
    249.     }  
    250.       
    251.     /** 
    252.      * 公钥解密 
    253.      * @desc  
    254.      * @param data 
    255.      * @param publicKey 
    256.      * @return 
    257.      * @throws Exception 
    258.      */  
    259.     public static String decryptByPublicKey(String data,  
    260.             RSAPublicKey publicKey) throws Exception {  
    261.         // 模长  
    262.         int key_len = publicKey.getModulus().bitLength() / 8;  
    263.         byte[] bytes = data.getBytes();  
    264.         byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
    265.         // 如果密文长度大于模长则要分组解密  
    266.         String ming = "";  
    267.         byte[][] arrays = splitArray(bcd, key_len);  
    268.         for (byte[] arr : arrays) {  
    269.             ming += new String(decryptByPublicKey(arr, publicKey));  
    270.         }  
    271.         return ming;  
    272.     }  
    273.       
    274.     /** 
    275.      * 公钥解密 
    276.      * @desc  
    277.      * @param data 
    278.      * @param publicKey 
    279.      * @return 
    280.      * @throws Exception 
    281.      */  
    282.     public static byte[] decryptByPublicKey(byte[] data,  
    283.             RSAPublicKey publicKey) throws Exception {  
    284.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
    285.         cipher.init(Cipher.DECRYPT_MODE, publicKey);  
    286.         return cipher.doFinal(data);  
    287.     }  
    288.   
    289.     /** 
    290.      * ASCII码转BCD码 
    291.      *  
    292.      */  
    293.     private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {  
    294.         byte[] bcd = new byte[asc_len / 2];  
    295.         int j = 0;  
    296.         for (int i = 0; i < (asc_len + 1) / 2; i++) {  
    297.             bcd[i] = asc_to_bcd(ascii[j++]);  
    298.             bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));  
    299.         }  
    300.         return bcd;  
    301.     }  
    302.   
    303.     private static byte asc_to_bcd(byte asc) {  
    304.         byte bcd;  
    305.   
    306.         if ((asc >= '0') && (asc <= '9'))  
    307.             bcd = (byte) (asc - '0');  
    308.         else if ((asc >= 'A') && (asc <= 'F'))  
    309.             bcd = (byte) (asc - 'A' + 10);  
    310.         else if ((asc >= 'a') && (asc <= 'f'))  
    311.             bcd = (byte) (asc - 'a' + 10);  
    312.         else  
    313.             bcd = (byte) (asc - 48);  
    314.         return bcd;  
    315.     }  
    316.   
    317.     /** 
    318.      * BCD转字符串 
    319.      */  
    320.     private static String bcd2Str(byte[] bytes) {  
    321.         char temp[] = new char[bytes.length * 2], val;  
    322.   
    323.         for (int i = 0; i < bytes.length; i++) {  
    324.             val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);  
    325.             temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
    326.   
    327.             val = (char) (bytes[i] & 0x0f);  
    328.             temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
    329.         }  
    330.         return new String(temp);  
    331.     }  
    332.   
    333.     /** 
    334.      * 拆分字符串 
    335.      */  
    336.     private static String[] splitString(String string, int len) {  
    337.         int x = string.length() / len;  
    338.         int y = string.length() % len;  
    339.         int z = 0;  
    340.         if (y != 0) {  
    341.             z = 1;  
    342.         }  
    343.         String[] strings = new String[x + z];  
    344.         String str = "";  
    345.         for (int i = 0; i < x + z; i++) {  
    346.             if (i == x + z - 1 && y != 0) {  
    347.                 str = string.substring(i * len, i * len + y);  
    348.             } else {  
    349.                 str = string.substring(i * len, i * len + len);  
    350.             }  
    351.             strings[i] = str;  
    352.         }  
    353.         return strings;  
    354.     }  
    355.   
    356.     /** 
    357.      * 拆分数组 
    358.      */  
    359.     private static byte[][] splitArray(byte[] data, int len) {  
    360.         int x = data.length / len;  
    361.         int y = data.length % len;  
    362.         int z = 0;  
    363.         if (y != 0) {  
    364.             z = 1;  
    365.         }  
    366.         byte[][] arrays = new byte[x + z][];  
    367.         byte[] arr;  
    368.         for (int i = 0; i < x + z; i++) {  
    369.             arr = new byte[len];  
    370.             if (i == x + z - 1 && y != 0) {  
    371.                 System.arraycopy(data, i * len, arr, 0, y);  
    372.             } else {  
    373.                 System.arraycopy(data, i * len, arr, 0, len);  
    374.             }  
    375.             arrays[i] = arr;  
    376.         }  
    377.         return arrays;  
    378.     }  
    379. }  

    JAVA - RSA实现

    1. package com.dyhdyh.encrypt;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6. import java.io.InputStreamReader;  
    7. import java.security.KeyFactory;  
    8. import java.security.NoSuchAlgorithmException;  
    9. import java.security.interfaces.RSAPrivateKey;  
    10. import java.security.interfaces.RSAPublicKey;  
    11. import java.security.spec.InvalidKeySpecException;  
    12. import java.security.spec.PKCS8EncodedKeySpec;  
    13. import java.security.spec.X509EncodedKeySpec;  
    14.   
    15. import javax.crypto.Cipher;  
    16.   
    17. import org.bouncycastle.jce.provider.BouncyCastleProvider;  
    18.   
    19. import sun.misc.BASE64Decoder;  
    20.   
    21. /** 
    22.  * 用于java平台的RSA加密解密 
    23.  *  
    24.  * @desc 
    25.  * @author dengyuhan 
    26.  * @create 2016-3-31 下午2:36:18 
    27.  */  
    28. public class RSA {  
    29.     private static final String ALGORITHM = "RSA";  
    30.     private static final String TRANSFORMATION = "RSA";  
    31.   
    32.     /** 
    33.      * 从文件中输入流中加载公钥 
    34.      *  
    35.      * @param in 
    36.      *            公钥输入流 
    37.      * @throws Exception 
    38.      *             加载公钥时产生的异常 
    39.      */  
    40.     public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {  
    41.         try {  
    42.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
    43.             String readLine = null;  
    44.             StringBuilder sb = new StringBuilder();  
    45.             while ((readLine = br.readLine()) != null) {  
    46.                 if (readLine.charAt(0) == '-') {  
    47.                     continue;  
    48.                 } else {  
    49.                     sb.append(readLine);  
    50.                     sb.append('\r');  
    51.                 }  
    52.             }  
    53.             return loadPublicKey(sb.toString());  
    54.         } catch (IOException e) {  
    55.             throw new Exception("公钥数据流读取错误");  
    56.         } catch (NullPointerException e) {  
    57.             throw new Exception("公钥输入流为空");  
    58.         }  
    59.     }  
    60.   
    61.     /** 
    62.      * 从字符串中加载公钥 
    63.      *  
    64.      * @param publicKeyStr 
    65.      *            公钥数据字符串 
    66.      * @return 
    67.      * @throws Exception 
    68.      *             加载公钥时产生的异常 
    69.      */  
    70.     public static RSAPublicKey loadPublicKey(String publicKeyStr)  
    71.             throws Exception {  
    72.         try {  
    73.             BASE64Decoder base64Decoder = new BASE64Decoder();  
    74.             byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);  
    75.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
    76.             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);  
    77.             return (RSAPublicKey) keyFactory.generatePublic(keySpec);  
    78.         } catch (NoSuchAlgorithmException e) {  
    79.             throw new Exception("无此算法");  
    80.         } catch (InvalidKeySpecException e) {  
    81.             throw new Exception("公钥非法");  
    82.         } catch (IOException e) {  
    83.             throw new Exception("公钥数据内容读取错误");  
    84.         } catch (NullPointerException e) {  
    85.             throw new Exception("公钥数据为空");  
    86.         }  
    87.     }  
    88.   
    89.     /** 
    90.      * 从文件中加载私钥 
    91.      *  
    92.      * @param in 
    93.      *            私钥输入流 
    94.      * @return 
    95.      * @throws Exception 
    96.      */  
    97.     public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {  
    98.         try {  
    99.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
    100.             String readLine = null;  
    101.             StringBuilder sb = new StringBuilder();  
    102.             while ((readLine = br.readLine()) != null) {  
    103.                 if (readLine.charAt(0) == '-') {  
    104.                     continue;  
    105.                 } else {  
    106.                     sb.append(readLine);  
    107.                     sb.append('\r');  
    108.                 }  
    109.             }  
    110.             return loadPrivateKey(sb.toString());  
    111.         } catch (IOException e) {  
    112.             throw new Exception("私钥数据读取错误");  
    113.         } catch (NullPointerException e) {  
    114.             throw new Exception("私钥输入流为空");  
    115.         }  
    116.     }  
    117.   
    118.     /** 
    119.      * 从字符串中加载私钥 
    120.      *  
    121.      * @desc 
    122.      * @param privateKeyStr 
    123.      *            私钥字符串 
    124.      * @return 
    125.      * @throws Exception 
    126.      */  
    127.     public static RSAPrivateKey loadPrivateKey(String privateKeyStr)  
    128.             throws Exception {  
    129.         try {  
    130.             BASE64Decoder base64Decoder = new BASE64Decoder();  
    131.             byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);  
    132.             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);  
    133.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
    134.             return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);  
    135.         } catch (NoSuchAlgorithmException e) {  
    136.             throw new Exception("无此算法");  
    137.         } catch (InvalidKeySpecException e) {  
    138.             throw new Exception("私钥非法");  
    139.         } catch (IOException e) {  
    140.             throw new Exception("私钥数据内容读取错误");  
    141.         } catch (NullPointerException e) {  
    142.             throw new Exception("私钥数据为空");  
    143.         }  
    144.     }  
    145.   
    146.     /** 
    147.      * 公钥加密 
    148.      *  
    149.      * @param data 
    150.      * @param publicKey 
    151.      * @return 
    152.      * @throws Exception 
    153.      */  
    154.     public static String encryptByPublicKey(String data, RSAPublicKey publicKey)  
    155.             throws Exception {  
    156.         // 模长  
    157.         int key_len = publicKey.getModulus().bitLength() / 8;  
    158.         // 加密数据长度 <= 模长-11  
    159.         String[] datas = splitString(data, key_len - 11);  
    160.         String mi = "";  
    161.         // 如果明文长度大于模长-11则要分组加密  
    162.         for (String s : datas) {  
    163.             mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));  
    164.         }  
    165.         return mi;  
    166.     }  
    167.   
    168.     /** 
    169.      * 公钥加密 
    170.      * @desc  
    171.      * @param data 
    172.      * @param publicKey 
    173.      * @return 
    174.      * @throws Exception 
    175.      */  
    176.     public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)  
    177.             throws Exception {  
    178.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
    179.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
    180.         return cipher.doFinal(data);  
    181.     }  
    182.   
    183.     /** 
    184.      * 私钥加密 
    185.      * @desc  
    186.      * @param data 
    187.      * @param privateKey 
    188.      * @return 
    189.      * @throws Exception 
    190.      */  
    191.     public static byte[] encryptByPrivateKey(byte[] data,  
    192.             RSAPrivateKey privateKey) throws Exception {  
    193.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
    194.         cipher.init(Cipher.ENCRYPT_MODE, privateKey);  
    195.         return cipher.doFinal(data);  
    196.     }  
    197.       
    198.     /** 
    199.      * 私钥加密 
    200.      * @desc  
    201.      * @param data 
    202.      * @param privateKey 
    203.      * @return 
    204.      * @throws Exception 
    205.      */  
    206.     public static String encryptByPrivateKey(String data,  
    207.             RSAPrivateKey privateKey) throws Exception {  
    208.         // 模长  
    209.         int key_len = privateKey.getModulus().bitLength() / 8;  
    210.         // 加密数据长度 <= 模长-11  
    211.         String[] datas = splitString(data, key_len - 11);  
    212.         String mi = "";  
    213.         // 如果明文长度大于模长-11则要分组加密  
    214.         for (String s : datas) {  
    215.             mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));  
    216.         }  
    217.         return mi;  
    218.     }  
    219.   
    220.     /** 
    221.      * 私钥解密 
    222.      *  
    223.      * @param data 
    224.      * @param privateKey 
    225.      * @return 
    226.      * @throws Exception 
    227.      */  
    228.     public static String decryptByPrivateKey(String data,  
    229.             RSAPrivateKey privateKey) throws Exception {  
    230.         // 模长  
    231.         int key_len = privateKey.getModulus().bitLength() / 8;  
    232.         byte[] bytes = data.getBytes();  
    233.         byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
    234.         // 如果密文长度大于模长则要分组解密  
    235.         String ming = "";  
    236.         byte[][] arrays = splitArray(bcd, key_len);  
    237.         for (byte[] arr : arrays) {  
    238.             ming += new String(decryptByPrivateKey(arr, privateKey));  
    239.         }  
    240.         return ming;  
    241.     }  
    242.       
    243.     /** 
    244.      * 私钥解密 
    245.      * @desc  
    246.      * @param data 
    247.      * @param privateKey 
    248.      * @return 
    249.      * @throws Exception 
    250.      */  
    251.     public static byte[] decryptByPrivateKey(byte[] data,  
    252.             RSAPrivateKey privateKey) throws Exception {  
    253.         Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider());  
    254.         cipher.init(Cipher.DECRYPT_MODE, privateKey);  
    255.         return cipher.doFinal(data);  
    256.     }  
    257.       
    258.     /** 
    259.      * 公钥解密 
    260.      * @desc  
    261.      * @param data 
    262.      * @param publicKey 
    263.      * @return 
    264.      * @throws Exception 
    265.      */  
    266.     public static String decryptByPublicKey(String data,  
    267.             RSAPublicKey publicKey) throws Exception {  
    268.         // 模长  
    269.         int key_len = publicKey.getModulus().bitLength() / 8;  
    270.         byte[] bytes = data.getBytes();  
    271.         byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
    272.         // 如果密文长度大于模长则要分组解密  
    273.         String ming = "";  
    274.         byte[][] arrays = splitArray(bcd, key_len);  
    275.         for (byte[] arr : arrays) {  
    276.             ming += new String(decryptByPublicKey(arr, publicKey));  
    277.         }  
    278.         return ming;  
    279.     }  
    280.       
    281.     /** 
    282.      * 公钥解密 
    283.      * @desc  
    284.      * @param data 
    285.      * @param publicKey 
    286.      * @return 
    287.      * @throws Exception 
    288.      */  
    289.     public static byte[] decryptByPublicKey(byte[] data,  
    290.             RSAPublicKey publicKey) throws Exception {  
    291.         Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider());  
    292.         cipher.init(Cipher.DECRYPT_MODE, publicKey);  
    293.         return cipher.doFinal(data);  
    294.     }  
    295.   
    296.     /** 
    297.      * ASCII码转BCD码 
    298.      *  
    299.      */  
    300.     private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {  
    301.         byte[] bcd = new byte[asc_len / 2];  
    302.         int j = 0;  
    303.         for (int i = 0; i < (asc_len + 1) / 2; i++) {  
    304.             bcd[i] = asc_to_bcd(ascii[j++]);  
    305.             bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));  
    306.         }  
    307.         return bcd;  
    308.     }  
    309.   
    310.     private static byte asc_to_bcd(byte asc) {  
    311.         byte bcd;  
    312.   
    313.         if ((asc >= '0') && (asc <= '9'))  
    314.             bcd = (byte) (asc - '0');  
    315.         else if ((asc >= 'A') && (asc <= 'F'))  
    316.             bcd = (byte) (asc - 'A' + 10);  
    317.         else if ((asc >= 'a') && (asc <= 'f'))  
    318.             bcd = (byte) (asc - 'a' + 10);  
    319.         else  
    320.             bcd = (byte) (asc - 48);  
    321.         return bcd;  
    322.     }  
    323.   
    324.     /** 
    325.      * BCD转字符串 
    326.      */  
    327.     private static String bcd2Str(byte[] bytes) {  
    328.         char temp[] = new char[bytes.length * 2], val;  
    329.   
    330.         for (int i = 0; i < bytes.length; i++) {  
    331.             val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);  
    332.             temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
    333.   
    334.             val = (char) (bytes[i] & 0x0f);  
    335.             temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
    336.         }  
    337.         return new String(temp);  
    338.     }  
    339.   
    340.     /** 
    341.      * 拆分字符串 
    342.      */  
    343.     private static String[] splitString(String string, int len) {  
    344.         int x = string.length() / len;  
    345.         int y = string.length() % len;  
    346.         int z = 0;  
    347.         if (y != 0) {  
    348.             z = 1;  
    349.         }  
    350.         String[] strings = new String[x + z];  
    351.         String str = "";  
    352.         for (int i = 0; i < x + z; i++) {  
    353.             if (i == x + z - 1 && y != 0) {  
    354.                 str = string.substring(i * len, i * len + y);  
    355.             } else {  
    356.                 str = string.substring(i * len, i * len + len);  
    357.             }  
    358.             strings[i] = str;  
    359.         }  
    360.         return strings;  
    361.     }  
    362.   
    363.     /** 
    364.      * 拆分数组 
    365.      */  
    366.     private static byte[][] splitArray(byte[] data, int len) {  
    367.         int x = data.length / len;  
    368.         int y = data.length % len;  
    369.         int z = 0;  
    370.         if (y != 0) {  
    371.             z = 1;  
    372.         }  
    373.         byte[][] arrays = new byte[x + z][];  
    374.         byte[] arr;  
    375.         for (int i = 0; i < x + z; i++) {  
    376.             arr = new byte[len];  
    377.             if (i == x + z - 1 && y != 0) {  
    378.                 System.arraycopy(data, i * len, arr, 0, y);  
    379.             } else {  
    380.                 System.arraycopy(data, i * len, arr, 0, len);  
    381.             }  
    382.             arrays[i] = arr;  
    383.         }  
    384.         return arrays;  
    385.     }  
    386. }  

    JAVA的RSA跟Android的RSA有所不同:

    1.加载key的时候,JAVA上用的是BASE64Decoder

    1. BASE64Decoder base64Decoder = new BASE64Decoder();  
    2. byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);  

    而Android上用的Base64这个地方只是API不一样,作用是一样的
    1. byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);  


    2.在JAVA平台上调用Cipher.getInstance()的时候,需要多传一个参数,也就是BouncyCastleProvider的实例:

    1. Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider());  

    这个类jdk上是没有的,所以需要添加一个jar包bcprov-jdk15-143.jar



    如果不这样做,JAVA上解密的时候就会抛出一个BadPaddingException

    1. Exception in thread "main" javax.crypto.BadPaddingException: Blocktype mismatch: 0  
    2.     at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:332)  
    3.     at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272)  
    4.     at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)  
    5.     at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)  
    6.     at javax.crypto.Cipher.doFinal(Cipher.java:2087)  
    7.     at com.dyhdyh.encrypt.RSA.decryptByPrivateKey(RSA.java:255)  
    8.     at com.dyhdyh.encrypt.RSA.decryptByPrivateKey(RSA.java:238)  
    这是因为Android的加密标准与JAVA的加密标准不一致导致,Android上的RSA实现是"RSA/None/NoPadding",而标准JDK实现是"RSA/None/PKCS1Padding",这造成了在Android上加密后无法在服务器上解密


    最后来看看怎样混合加密(这里只举一种方式,附件里有完整的)


    Android上加密

    1.将openssl生成出来的公钥,放入assets文件夹内(不一定要放这里,只要能拿到文件内容就行)。



    2.加载放在assets文件里的公钥

    1. //加载RSA公钥  
    2. RSAPublicKey rsaPublicKey = RSA.loadPublicKey(getAssets().open("rsa_public_key.pem"));  

    3.再生成一个AES的密钥,用于AES加密
    1. //生成一个AES密钥  
    2. String aesKey=AES.generateKeyString();  

    4.通过RSA的公钥来加密刚刚生成的AES密钥
    1. //用RSA公钥加密AES的密钥  
    2. String encryptAesKey = RSA.encryptByPublicKey(aesKey, rsaPublicKey);  

    5.最后使用AES来加密需要传输的数据,AES加密需要传入两个参数,第一个是明文数据,第二个是3步生成出来的密钥

    1. //再使用AES加密内容,传给服务器  
    2. String encryptContent = AES.encrypt(content, aesKey);  

    6.第5步返回的字符串就是加密过后的数据,最后将4和5传给服务端,接下来就是服务端的事情了。


    客户端传过来密文之后,接下来就需要服务端来解密了


    JAVA解密

    1.加载RSA私钥(这里的私钥是跟客户端的公钥是成对的)

    1. //加载私钥  
    2. RSAPrivateKey privateKey = RSA.loadPrivateKey(new FileInputStream("G:/RSA密钥/pkcs8_rsa_private_key.pem"));  


    2.通过RSA的私钥解密客户端传来的AES-KEY(也就是客户端的第4),因为这个key是加过密的,所以我们需要先将key解密成明文
    1. //解密AES-KEY  
    2. String decryptAesKey = RSA.decryptByPrivateKey(aesKey, privateKey);  

    3.AES-KEY加密成明文之后,现在可以拿这个key来解密客户端传过来的数据了
    1. //AES解密数据  
    2. String decrypt = AES.decrypt(content, decryptAesKey);  


    RSA-AES混合加密就是这个样子,有什么问题请跟帖回复,我会继续改进


    最后附上完整demo

    http://download.csdn.net/detail/aa464971/9478798
    展开全文
  • Android网络请求加密机制详解

    千次阅读 2018-07-02 10:11:03
    Android开发中,难免会遇到需要加解密一些数据内容存到本地文件、或者通过网络传输到其他服务器和设备的问题,但并不是使用了加密就绝对安全了,如果加密函数使用不正确,加密数据很容易受到逆向破解攻击。...
    展开全文
  • http请求加密

    千次阅读 2016-07-11 16:58:43
    MD5和RSA是网络传输中最常用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了。但这两种算法使用环境有差异,刚好互补。 一、MD5算法 首先MD5是不可逆的,只能加密而不能解密。比如明文是yanzi...
  • 虽然使用的是HTTPS的方式进行http请求的,但还是被Fiddler抓到了明文内容。因此,需要对之前未加密的登录信息进行加密。在网上搜到一篇关于AES+RSA加密方案的文章,如下面链接所示,按照该方案成功解决了加密问题,...
  • 加密的抓包截图 加密之后的抓包截图 基本需求及概念 AES算法 AES基本原理及算法流程 AES算法流程 RSA算法 RSA算法基本原理及流程 RSA算法实现流程 AES与RSA相结合数据加密方案 Android端 AESRSA结合实践 基本要求 ...
  • 虽然使用的是HTTPS的方式进行http请求的,但还是被Fiddler抓到了明文内容。因此,需要对之前未加密的登录信息进行加密。在网上搜到一篇关于AES+RSA加密方案的文章,如下面链接所示,按照该方案成功解决了加密问题,...
  • 目前的数据加密技术根据加密密钥类型可分私钥加密(对称加密)系统和公钥加密(非对称加密)系统。  对称加密算法是较传统的加密体制,通信双方在加/解密过程中使用他们共享的单一密钥,鉴于其算法简单和加密速度...
  • 加密的抓包截图 加密之后的抓包截图 基本需求及概念 AES算法 AES基本原理及算法流程 AES算法流程 RSA算法 RSA算法基本原理及流程 RSA算法实现流程 AES与RSA相结合数据加密方案 Android端 AESRSA结合实践 ...
  • 加密http请求返回结果

    2019-09-12 14:34:50
    因为发现有些其他偷懒的开发者可能盗用我们restful服务器的api接口,所以对response进行加密是一个不错的解决方法。 ##HTTPS 也许你马上会想到用https,但是我们可以通过在wikipedia上发现有这么一段对https的解释...
  • 第一次对请求体进行加密操作,记录一下大坑。废话不多说看代码我用的novate网络框架转载地址---https://blog.csdn.net/u013651026/article/details/79294447总体请求方式如下----Novate novate = new Novate.Builder...
  • 心想 这不是很简单吗 直接在拦截器中获取到要上传的数据 然后加密 重新赋值 很简单嘛 但是实践起来 我真的气的想要骂娘 太坑了好吗。。。。无语直接就打到我的脸上 废话不多说 让我重温一下这些坑 第一步 在网络...
  • 第一次对请求体进行加密操作,记录一下大坑。废话不多说看代码 我用的novate网络框架 转载地址---https://blog.csdn.net/u013651026/article/details/79294447 总体请求方式如下---- Novate novate = new ...
  • 大致什么样的app先暂时不说,后面会详细介绍这个app的开发流程和架构,不过先要解决一些技术前提问题,技术问题就是需要分析解密当前短视频四小龙:抖音,火山,秒拍,快手这四家短视频的数据请求加密协议,只有破解...
  • 进行性能测试时,有可能遇到一种场景:接口请求由于安全问题,需要进行加密发送。 这种场景下,使用Jmeter实现性能测试,则也需要使用同样的加密规则发送请求报文。 要实现此类性能测试有几种策略: 直接去除密文...
  • 解决这个问题最好的方法当然是使用Https协议,但是Https协议需要像权威机构申请证书才能保证足够的...我们现在的场景只考虑在Http请求加密,Http响应中没有敏感信息,暂时不考虑加密。首先考虑下对称加密的方式,这种
  • 一、逆向分析年前必须搞定短视频四小龙,之前已经搞定某音和某山小视频了,那么今天继续来搞下一个,在之前一篇文章中已经详细分析了不了解的同学,可以点击详情:某音和某山小视频的数据请求加密协议,通过IDA动态...
  • 这位大牛也很久没有更新了,在高校体育的大更之后,原先的登陆方式已经失效了,事实上只要在大牛的项目上稍加修改即可,下面就是关于这部分需要修改的内容,对新版高校体育get请求加密算法的逆向。 抓包 host...
  • 大白话:由于 Android P(版本27以上) 限制了明文流量的网络请求,非加密的流量请求都会被系统禁止掉。所以如果当前应用的请求是 htttp 请求,而非 https ,这样就会导系统禁止当前应用进行该请求。 专业
  • 前两天Androidandroid 打包升升级sdk版本,从27 升级到29,发现原来的http请求访问不了,后百度发现,原来是在Android (9.0)系统的设备上,如果应用使用的是非加密的明文流量的http网络请求,则会导致该应用无法进行...
  • Android http网络请求框架搭建

    千次阅读 2016-05-23 11:19:44
    android上网络请求大致分为使用socket和http,普通应用大多使用http或者https,今天主要介绍http,实现目标通过使用http搭建一套简单的Android网络请求框架。 待续。。。
  • 本文档 当中所用到的: const $request = this.request const post = $request.call('passport/wxLogin',data) post.then(res=>...1、js生成接口请求参数签名加密 定义规则: 对所有发起请求的参...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,019
精华内容 9,607
关键字:

安卓http请求加密