版权说明 :《Android加密算法之非对称加密RSA》于当前CSDN博客乘月网属同一原创,转载请说明出处,谢谢。

上文《Android加密算法之对称加密AES》提到与对称加密算法相对应的非对称加密RSA,本文正式进入该算法的简单讲解和使用。

非对称加密算法:加密和解密使用不同密钥的加密算法,也称为公私钥加密。不同的秘钥指作公开密钥(publickey)和私有秘钥(privatekey),两个天生一对,密不可分。如果用公钥对数据进行加密,只有用对应的私钥才能解密,如果用私钥对数据进行加密,那么只有用对应的公钥才能解密。

上述可能会给小伙伴们一个很友好的疑问,都可以互相加解密,为什么有公私之分,随便给两个密钥公私身份可以吗?

首先从长度上来比较,私钥长度明显比公钥高不少,这意味着对密钥的记忆难度有着很大差别,另外在逆向破解中,由于该算法特性,长度短的公钥想逆向推导出私钥的代价是相当昂贵的,相反私钥推导出公钥相对来说简单到爆炸,因此我们会本能的想到,长度短的密钥公开给众人使用解开自己的公布的密文,而长度长的密钥由自己私有保管。

其次从非对称加密的设计本意来说:公钥加密,私钥解密;私钥加签,公钥验签。设想A和B两位是好友,A持有公钥PK-A和私钥Sk-A,B持有公钥PK-B和私钥SK-B,PK-A和PK-B都是公开的,全世界人都知道,而SK-A和SK-B分别只有A和B自己知道。分析以下场景:

场景1:A给B发信息,在通信过程中,信息内容可能被非法之徒劫持,如果A没有作加密处理,那就.....后果可想而知,那么A会选择用什么密钥加密?我们逐一排除,选择PK-A?加密完后,只有SK-A解密,这倒好了,劫持者不知道SK-A,无法解密就算了,B也不知道啊,也解不了,PASS掉!选SK-A?OK,那么只能PK-A解密,而B和劫持者都知道PK-A,都能解密,这跟没加密有什么区别?狠狠的PASS掉!选SK-B?你想多了,只有B知道SK-B啊,没得选,只能选PK-B,那么只能用SK-B解密了,劫持者并不知道SK-B,只能干看着密文着急,而B能轻松解密并给查看A给自己发的内容了。

场景2:A对B突发好感,给其写了一封匿名电子情书,B看了后很感动但是以为是C写的,于是向作为好友的A分享自己的喜悦,这时候A着急了,说是自己写的,B就是不相信,以为在逗他。没办法,A只能出大招,高度自信地告诉B把这封信上的一处签名解开就是A的名字,那么问题来了,A用什么密钥来制作签名的?为啥这么自信?PK-B?,全世界人都可以制作这个签名,挂掉!SK-B?没人知道啊,怎么制作啊?毙掉!PK-A?别人也知道啊,也可以制作这个签名啊,那么只能SK-A了,只有A能做这样的签名,这时候B拿A的PK-A验证这个签名,验证的结果正是A的姓名。从此二人过上了愉快的基友生活.....咦。。。。。。。。

相信上面两个场景,会让小伙伴们感悟颇深,无法忘怀,理解为重,理解为重哈。。。

回到主题,之前文章《Android加密算法之对称加密AES》我们知道,对称加密算法具有算法公开、计算量小、加密速度快、加密效率高等优点,非对称加密算法则比之慢数千倍,这一点笔者在做RSA加解密的时候深有感触,这里提醒Android Developer在做非对称加密的时候最好能在子线程中执行,否则容易造成ANR。话说回来,非对称加密算法在保护通信安全方面,具有对称加密难以企及的优势,具体以后文章会更新拓展。

非对称加密主要使用的是RSA算法,Android RSA算法一样沿用java的API,公私钥长度建议为2048位(至少1024及以上,以下已被破解),推荐"RSA/ECB/OAEPWithSHA256AndMGF1Padding"填充方式,否则容易被重放攻击。下面为RSA实现工具类RSAUtils.java :

package cn.icheny.security;import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import android.util.Base64;/*** RSA加密,解密工具* * @author Cheny*/public class RSAUtils {// 推荐的RSA加密模式,否则容易被重放攻击private static final String RSA_ECB_OAEP_WITH_SHA256_AND_MGF1_PADDING = "RSA/ECB/OAEPWithSHA256AndMGF1Padding";private static final String RSA = "RSA";/*** 生成秘钥,公钥和私钥* * @return Base64编码的公钥和私钥 secretKeys[]{rsaPublicKey,rsaPrivateKey}*/public static String[] generateSecretKey() {String[] secretKeys = null;try {// 构建密钥对生成器KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);// 初始化秘钥长度 2048位(512位已被破解,至少用1024及以上)keyPairGenerator.initialize(2048);// 生成密钥对,包含公钥私钥KeyPair keyPair = keyPairGenerator.generateKeyPair();// 公钥对象,RSAPublicKey为PublicKey子接口RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();// 公钥对象,RSAPrivateKey为PrivateKey子接口RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();// 公钥byte[] publicKeyBytes = rsaPublicKey.getEncoded();// 私钥byte[] privateKeyBytes = rsaPrivateKey.getEncoded();secretKeys = new String[2];// 对公私钥Base64转码,加解密时需要把转码后的公私钥进行Base64还原secretKeys[0] = Base64.encodeToString(publicKeyBytes, Base64.DEFAULT);secretKeys[1] = Base64.encodeToString(privateKeyBytes, Base64.DEFAULT);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return secretKeys;}/*** 公钥加密* * @param plaintext 明文* @param rsaPublicKey 公钥* @return Base64编码的密文*/public static String encryptByPublicKey(String plaintext, String rsaPublicKey) {try {// Base64还原公钥byte[] publicKeyBytes = Base64.decode(rsaPublicKey, Base64.DEFAULT);// X509编码秘钥规范X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);// 秘钥工厂KeyFactory keyFactory = KeyFactory.getInstance(RSA);// 还原公钥对象,PublicKey为RSAPublicKey父接口PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);// Cipher对象,指定算法模式Cipher cipher = Cipher.getInstance(RSA_ECB_OAEP_WITH_SHA256_AND_MGF1_PADDING);// 初始化,指定为加密模式cipher.init(Cipher.ENCRYPT_MODE, publicKey);// 执行加密byte[] result = cipher.doFinal(plaintext.getBytes("UTF-8"));return Base64.encodeToString(result, Base64.DEFAULT); // 对密文Base64转码,解密时需要把转码后的密文进行Base64还原} catch (InvalidKeyException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (InvalidKeySpecException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return null;}/*** 公钥解密* * @param ciphertext 密文* @param rsaPublicKey 公钥* @return Base64编码的密文*/public static String decryptByPublicKey(String ciphertext, String rsaPublicKey) {try {// Base64还原公钥byte[] publicKeyBytes = Base64.decode(rsaPublicKey, Base64.DEFAULT);// X509秘钥编码规范X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);// 秘钥工厂KeyFactory keyFactory = KeyFactory.getInstance(RSA);// 还原公钥对象,PublicKey为RSAPublicKey父接口PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);// Cipher对象,指定算法模式Cipher cipher = Cipher.getInstance(RSA_ECB_OAEP_WITH_SHA256_AND_MGF1_PADDING);// 初始化,指定为解密模式cipher.init(Cipher.DECRYPT_MODE, publicKey);// Base64还原密文byte[] cipherBytes = Base64.decode(ciphertext, Base64.DEFAULT);// 执行解密byte[] result = cipher.doFinal(cipherBytes);return new String(result, "UTF-8");} catch (InvalidKeyException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (InvalidKeySpecException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return null;}/*** 私钥加密* * @param plaintext  明文* @param rsaPrivateKey 私钥* @return Base64编码的密文*/public static String encryptByPrivateKey(String plaintext, String rsaPrivateKey) {try {// Base64还原私钥byte[] privateKeyBytes = Base64.decode(rsaPrivateKey, Base64.DEFAULT);// PKCS8秘钥编码规范PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);// 秘钥工厂KeyFactory keyFactory = KeyFactory.getInstance(RSA);// 还原公钥对象,PrivateKey为RSAPrivateKey父接口PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);// Cipher对象,指定算法模式Cipher cipher = Cipher.getInstance(RSA_ECB_OAEP_WITH_SHA256_AND_MGF1_PADDING);// 初始化,指定为加密模式cipher.init(Cipher.ENCRYPT_MODE, privateKey);// 执行加密byte[] result = cipher.doFinal(plaintext.getBytes("UTF-8"));return Base64.encodeToString(result, Base64.DEFAULT);// 对密文Base64转码,解密时需要把转码后的密文进行Base64还原} catch (InvalidKeyException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (InvalidKeySpecException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return null;}/*** 私钥解密* * @param ciphertext  密文* @param rsaPrivateKey 秘钥* @return 明文*/public static String decryptByPrivateKey(String ciphertext, String rsaPrivateKey) {try {// Base64还原私钥byte[] privateKeyBytes = Base64.decode(rsaPrivateKey, Base64.DEFAULT);// PKCS8秘钥编码规范PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);// 秘钥工厂KeyFactory keyFactory = KeyFactory.getInstance(RSA);// 还原公钥对象,PrivateKey为RSAPrivateKey父接口PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);// Cipher对象,指定算法模式Cipher cipher = Cipher.getInstance(RSA_ECB_OAEP_WITH_SHA256_AND_MGF1_PADDING);// 初始化,指定为解密模式cipher.init(Cipher.DECRYPT_MODE, privateKey);// Base64还原密文byte[] cipherBytes = Base64.decode(ciphertext, Base64.DEFAULT);// 执行解密byte[] result = cipher.doFinal(cipherBytes);return new String(result, "UTF-8");} catch (InvalidKeyException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (InvalidKeySpecException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return null;}
}

个人习惯,代码中注释得很详细,所以就不在此话似唐僧了,与其一边看代码,一边看代码下文的解释让人视觉疲劳,还不如把注释写好,笔者深有体会。文章先到这,日后会继续更新。。。

Android加密算法之非对称加密RSA相关推荐

  1. php封装一个加密算法,PHP封装的非对称加密RSA算法示例

    本文实例讲述了PHP封装的非对称加密RSA算法.分享给大家供大家参考,具体如下: 将php的openssl扩展中的非对称加密函数封装成一个Rsa类. 需要注意的是,在windows上,需要打开open ...

  2. (1)非对称加密——RSA——史上最通俗的小白可看懂!

    摘要 我身边有几个年龄分布在4-6岁的小朋友.由于他们还都不能熟练地掌握100以内的加减法,所以我原计划的对称加密,在他们看来还是有点难.那非对称加密呢,需要他们能熟练进行三位数的乘法,我想就可以逐步 ...

  3. IOS 逆向开发(一)密码学 非对称加密RSA

    IOS 逆向开发(一)密码学 RSA 1. 密码学发展简介 2. 非对称加密RSA产生过程 3. RSA 数学原理 3.1 离散对数问题 3.1.1 原根 3.2 欧拉函数Φ 3.3 欧拉定理 3.4 ...

  4. 编解码base64、对称加密aes和非对称加密rsa

    base64 :(兼容所有bit8位的字符,然后用64种字符进行转码,达到一致性) 意思就是:考虑到多语言原因,有的特殊字符传输不兼容,因为很多都是只支持ASSIC码,那么特殊字符就会找不到对应的AS ...

  5. 加密基础知识二 非对称加密RSA算法和对称加密

    一.RSA的计算过程 上述过程中,出现了公钥(3233,17)和私钥(3233,2753),这两组数字是怎么找出来的呢?参考RSA算法原理(二) 首字母缩写说明:E是加密(Encryption)D是解 ...

  6. 【工具编写】python实现非对称加密RSA算法

    python实现非对称加密RSA算法 0x01 RSA算法介绍 RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用.RSA是1977年由罗纳德·李维斯特(Ron Rives ...

  7. 非对称加密RSA算法原理及实际应用场景

    非对称加密RSA算法原理及实际应用场景 引言 应用场景 RSA 算法原理 数学基础 质数 欧拉定理 模指数运算 小白理解 为什么需要足够大的质数 引言 我数学差的离谱,所以我朋友去学AI,我还在这搞这 ...

  8. c语言字符串非对称加密,RSA算法C语言实现(支持任意位密钥)

    之前分享过三种常用MD5.SHA2和AES加密算法(点这里)实现源码,前三者分别属于哈希加密和对称加密,而另一种很常用的非对称加密RSA算法实现这次分享出来.RSA算法的原理和用途大家可以网上自行搜索 ...

  9. 密码学03--go语言与非对称加密RSA算法的实现

    目录 1.对称加密的弊端 2.非对称加密 2.1 非对称加密使用场景 2.2 区分公私钥 2.3 非对称加密通信流程 2.4 非对称加密与对称加密 3.非对称加密RSA算法 3.1 RSA算法 3.2 ...

最新文章

  1. Windows任务计划创建计划,定时执行PowerShell命令
  2. docker (centOS 7) 使用笔记4 - etcd服务
  3. Java批量完成对文件夹下全部的css与js压缩,利用yuicompressor
  4. 如何在Jsp上传图片
  5. 分布与并行计算—生命游戏(Java)
  6. 使用常识 | 如何在word中添加勾选框
  7. c++中recvfrom函数_通俗易懂:快速理解网络编程中5种IO模型
  8. 鸿合科技成为AMX品牌全系列产品中国(大陆)总代理
  9. bzoj3322 最大生成树+LCA
  10. SOA webservice
  11. XML中的大于等于号,如何处理
  12. php 0x80070005,PHPIIS0x80070005解决方法
  13. dr.oracle黑钻面膜,dr.diamond是什么牌子?dr.diamond钻石面膜怎么样?
  14. 计算机如何驱动无线网络,详细教你电脑无线网卡驱动怎么安装
  15. html css星号选择器,CSS里面的星号*
  16. 团队管理8--管理工作框架及技能图谱
  17. 2019,华为一号文
  18. 使用讯飞语音识别的空指针错误
  19. 电脑连接上WiFi但是上不了网
  20. WHT20无线温湿度传感器 STM8S单片机

热门文章

  1. 全国种子双交会暨2023(天津)功能性农业·农业大健康大会
  2. 什么是网络安全?为什么要学网络安全?如何学习网络安全?
  3. springboot注解@Order的使用
  4. 天津博物馆镇馆之宝——玉壶春瓶
  5. pppoe拨号上网 路由器(Router) 网关
  6. 手写经典卷积神经网络-AlexNet
  7. GLSurfaceView+openGL播放VR视频/全景视频(VR解码器)
  8. 亚马逊云服务(AWS) 为机器学习扩圈 触及每一位AI工作者
  9. 家庭账务管理系统html,一种家庭财务管理信息系统的制作方法
  10. [WC2016] 论战捆竹竿 [学习笔记] 同余最短路