RSA

RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。

RSA的算法涉及三个参数,n、e1、e2。其中,n是两个大质数p、q的积,n的二进制表示时所占用的位数,就是所谓的密钥长度。e1和e2是一对相关的值,e1可以任意取。

算法过程

一、产生密钥

  1. 为了产生两个密钥,选取两个大素数,p和q,为了获得最大程度的安全性,两数的长度一样。计算乘积

    n=p*q;

  2. 随机取加密密钥e,使得e 和(p-1)(q-1) 互素,最后采用扩展欧几里得算法计算解密密钥d,

    d=e^-1 mod (p-1)(q-1)

    注意

    d和n也是互素。e和n是公开密钥,d是私人密钥。

    RSA加解密的算法完全相同,设A为明文,B为密文,则:

    ​ A=B^d mod n;

    ​ B=A^e mod n;

    公钥加密体制中,一般用公钥加密,私钥解密

    e1和e2可以互换使用,即:

    ​ A=B^e mod n;

    ​ B=A^d mod n;

    我们可以设计出一对公私密钥,加密密钥(公钥)为:KU =(e,n)=(3,33),解密密钥(私钥)为:KR =(d,n)=(7,33)。

二、英文数字化

 将明文信息数字化,并将每块两个数字分组。假定明文英文字母编码表为按字母顺序排列数值,即:

三、明文加密

**加密消息m时,首先将它分为比n小的数据分组(采用二级制数,选取小于n的2的最大次幂),也就是说,若果p和n为100位的素数,那么n将有200位,每个消息分组m应该小于200位长 **

 用户加密密钥(3,33) 将数字化明文分组信息加密成密文。由C≡M^e(mod n)得:

四、密文解密

用户B收到密文,若将其解密,只需要计算 M≡c^d(mod n)

 用户B得到明文信息为:11,05,25。根据上面的编码表将其转换为英文,我们又得到了恢复后的原文“key”

e值

最常用的三个e值:3, 17, 65537(2^16+1).

X.509中建议采用65537[1], PEM中建议采用3[37],PKCS#1建议采用3或65537[1345].

PKCS#1填充

RSA在应用中一般采用PKCS#1的标准进行填充

注意

  • 开头为00只为了保证原文大小小于私钥
  • 对于私钥操作,你可以把BT的值设为01,这时PS填充的FF,那么用00字节就可以区分填充数据和明文数据对于公钥操作,填充的都是非00字节,也能够用00字节区分开。如果你使用私钥加密,建议你BT使用01,保证了安全性。
  • 对于BT为02和01的,PS至少要有8个字节长,BT为02肯定是公钥加密,01肯定是私钥加密,要保证PS至少有八个字节长 。因为EB= 00+BT+PS+00+D=k, 所以D<=k-11,所以当我们使用128字节密钥对数据进行加密时,明文数据的长度不能超过过128-11=117字节当RSA要加密数据大于 k-11字节时怎么办呢?把明文数据按照D的最大长度分块然后逐块加密,最后把密文拼起来就行。明文长度小于117ps处填充数据即可

附JAVA代码

/**
* RSA algorithm.
*/
public static final String KEY_ALGORITHM = "RSA"; /**
* digital signature algorithm
*/
public static final String SIGNATURE_ALGORITHM = "SHA256withRSA"; /**
* Gets public key.
*/
private static final String PUBLIC_KEY = "RSAPublicKey"; /**
* Gets private key.
*/
private static final String PRIVATE_KEY = "RSAPrivateKey"; /**
* RSA maximum encryption text size.
*/
private static final int MAX_ENCRYPT_BLOCK = 117; /**
* RSA maximum decryption text size.
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* <p>
* Use the private key to generate digital signatures for the information.
* </p>
*
* @param data
* Encrypted data
* @param PrivateKey
* Private Key (BASE64 encoding)
* @return Digit signature (BASE64 encoding)
* @throws Exception
*/
public byte[] sign(byte[] data, String privateKey) {
try {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory;
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateK);
signature.update(data);
return signature.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) { e.printStackTrace();
} return null;
} /**
* <p>
* Verify digit signature.
* </p>
*
* @param data
* Encrypted data
* @param publicKey
* Public Key(BASE64 encoding)
* @param sign
* Digit signature
*
* @return result from verify
* @throws Exception
*
*/
public boolean verify(byte[] data, String publicKey, byte[] sign) {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory;
try {
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicK);
signature.update(data); return signature.verify(sign);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | SignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
} /**
* <P>
* Decrypted with the private key
* </p>
*
* @param encryptedData
* Encrypted data
* @param privateKey
* Private Key (BASE64 encoding)
* @return decryptedData
* @throws Exception
*/
public byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) {
byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory;
try {
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
ByteArrayOutputStream out = new ByteArrayOutputStream(); int inputLen = encryptedData.length;
int offSet = 0;
byte[] cache;
int i = 0; // 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
} out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
} byte[] decryptedData = out.toByteArray();
out.close(); return decryptedData;
} catch (Exception e) {
e.printStackTrace();
} return null; } /**
* <p>
* Encrypt with the public key.
* </p>
*
* @param data
* Plain text
* @param publicKey
* Public key(BASE64 encoding)
* @return encryptedData
* @throws Exception
*/
public byte[] encryptByPublicKey(byte[] data, String publicKey) {
byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory;
try {
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK); ByteArrayOutputStream out = new ByteArrayOutputStream();
int inputLen = data.length;
int offSet = 0;
byte[] cache;
int i = 0; // 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
} out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
} byte[] encryptedData = out.toByteArray();
out.close(); return encryptedData;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return null;
}

  1. 304 ↩︎

RSA详解的更多相关文章

  1. C#实现RSA加密和解密详解

    原文:C#实现RSA加密和解密详解 RSA加密解密源码: Code highlighting produced by Actipro CodeHighlighter (freeware) http:/ ...

  2. 安全体系(二)——RSA算法详解

    本文主要讲述RSA算法使用的基本数学知识.秘钥的计算过程以及加密和解密的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 1.概述 ...

  3. 密码疑云 (3)——详解RSA的加密与解密

    上一篇文章介绍了RSA涉及的数学知识,本章将应用这些知识详解RSA的加密与解密. RSA算法的密钥生成过程 密钥的生成是RSA算法的核心,它的密钥对生成过程如下: 1. 选择两个不相等的大素数p和q, ...

  4. 【iOS 使用github上传代码】详解

    [iOS 使用github上传代码]详解 一.github创建新工程 二.直接添加文件 三.通过https 和 SSH 操作两种方式上传工程 3.1https 和 SSH 的区别: 3.1.1.前者可 ...

  5. Hadoop集群搭建安装过程(二)(图文详解---尽情点击!!!)

    Hadoop集群搭建安装过程(二)(配置SSH免密登录)(图文详解---尽情点击!!!) 一.配置ssh无密码访问 ®生成公钥密钥对 1.在每个节点上分别执行: ssh-keygen -t rsa(一 ...

  6. Linux虚拟机安装(CentOS 6.5,图文详解,需要自查)

    Linux虚拟机的安装(图文详解) 下篇会接续Hadoop集群安装(以此为基础) 一.安装准备 VMWorkstation.linux系统镜像(以下以CentOS6.5为例) 二.安装过程详解 关闭防 ...

  7. Cordova 打包 Android release app 过程详解

    Cordova 打包 Android release app 过程详解 时间 -- :: SegmentFault 原文 https://segmentfault.com/a/119000000517 ...

  8. 【大数据】Linux下安装Hadoop(2.7.1)详解及WordCount运行

    一.引言 在完成了Storm的环境配置之后,想着鼓捣一下Hadoop的安装,网上面的教程好多,但是没有一个特别切合的,所以在安装的过程中还是遇到了很多的麻烦,并且最后不断的查阅资料,终于解决了问题,感 ...

  9. apache 虚拟主机详细配置:http.conf配置详解

    apache 虚拟主机详细配置:http.conf配置详解 Apache的配置文件http.conf参数含义详解 Apache的配置由httpd.conf文件配置,因此下面的配置指令都是在httpd. ...

随机推荐

  1. JPEG图片扩展信息读取与改动

    近日项目中须要用到往jpg图片中写入信息(非水印),经调研发现Android中已经封装了读写jpg图片扩展信息的api(ExifInterface). 相应api地址:http://developer ...

  2. swoole_table应用类

    <?php/* Redis可真能坑爷,原先的设计用redis保存临时数据,可到了实际应用(实际上也就是几十个人同时用),总是出现莫名其妙的问题,最常见的就是读不出数据来,调试了好多天,那问题还是 ...

  3. 联想拯救者s15k重装w10系统教程

    目的:1.自己平常健忘,且总是要重装系统,2.给看到此篇文章的人一点参考 ps:联想拯救者s15k系列,带有两个硬盘,一个是装系统的硬盘,大小约120G,一个是资料盘,大小约900G,系统重装在小硬盘 ...

  4. 基于Jq的手写插件

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  5. 如何方便的结果ajax使用html5的新type类型

    今天需要做手机端的输入表单自动生成器,突然就想到了手机端对input的输入类型支持还不错,于是翻遍了资料,有了下面的使用方法,闲话少说,上正文: html5现在可以用的新input type类型一共有 ...

  6. PHP中const,static,public,private,protected的区别

    原文地址:http://small.aiweimeng.top/index.php/archives/54.html const: 定义常量,一般定义后不可改变static: 静态,类名可以访问pub ...

  7. spark练习--由IP得到所在地

    今天我们就来介绍,如何根据一个IP来求出这个IP所在的地址是什么,首先我们如果要做这个内容,那么我们要有一个IP地址的所在地字典,这个我们可以在网上购买,形如: 1.0.1.0|1.0.3.255|1 ...

  8. uliweb的模版

    uliweb模版的文件名是与函数名相同的 以test为例: ***@Android:~/ablog# vim apps/blog/templates/test.html 编辑test.html的内容 ...

  9. Advanced Find and Replace(文件内容搜索替换工具)v7.8.1简体中文破解版

    Advanced Find and Replace是一款文件内容搜索工具,同时也是文件内容批量替换工具.支持通配符和正则表达式,方便快捷强大! 显示中文的方法:第二个菜单-Language-选 下载地 ...

  10. 20155217 2016-2017-2 《Java程序设计》第9周学习总结

    20155217 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 JBDC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商对接口直接操作 ...