RSA中pkcs1的填充方法具体是什么?
1)RSA_PKCS1_PADDING 填充模式,最常用的模式
要求:
输入 必须 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11
如果输入的明文过长,必须切割, 然后填充
输出 和modulus一样长
根据这个要求,对于512bit的密钥, block length = 512/8 – 11 = 53 字节
2) RSA_PKCS1_OAEP_PADDING
RSA_size(rsa) – 41
3)for RSA_NO_PADDING 不填充
RSA_size(rsa)
一般来说, 我们只用RSA来加密重要的数据,比如AES的key, 128bits = 16
加密的输出,总是等于key length
对同样的数据,用同样的key进行RSA加密, 每次的输出都会不一样; 但是这些加密的结果都能正确的解密
—————
预备知识
I2OSP – Integer-to-Octet-String primitive 大整数转换成字节串
I2OSP (x, xLen)
输入: x 待转换的非负整数
xLen 结果字节串的可能长度
————
加密原理 RSAEP ((n, e), m)
输入: (n,e) RSA公钥
m 值为0到n-1 之间一个大整数,代表消息
输出: c 值为0到n-1之间的一个大整数,代表密文
假定: RSA公钥(n,e)是有效的
步骤:
如果m不满足 0 2. 让 c = m^e % n (m的e次幂 除以n ,余数为c)
3. 输出 c
解密原理 RSADP (K, c)
输入: K RSA私钥,K由下面形式:
一对(n,d)
一个五元组(p, q, dP, dQ, qInv)
一个可能为空的三元序列(ri, di, ti), i=3,,u
c 密文
输出: m 明文
步骤:
如果密文c不满足 0 < c < n-1, 输出 'ciphertext repersentative out of range'
2. 按照如下方法计算m:
a. 如果使用私钥K的第一种形式(n, d), 就让 m = c^d % n (c的d次幂,除以n,余数为m)
b. 如果使用私钥K的第二种像是(p,q, dP, dQ, qInv)和(ri, di, ti),
--------------
----------------
加密 RSAES-PKCS1-V1_5-ENCRYPT ((n, e), M)
输入: (n, e) 接收者的公开钥匙, k表示n所占用的字节长度
M 要加密的消息, mLen表示消息的长度 mLen ≤ k – 11
输出: C 密文, 占用字节数 也为 k
步骤:
长度检查, 如果 mLen > k-11, 输出 “message too long”
2. EME-PKCS1-v1_5 编码
a) 生成一个 伪随机非零串PS , 长度为 k – mLen – 3, 所以至少为8, 因为 k-mLen>11
b) 将PS, M,以及其他填充串 一起编码为 EM, 长度为 k, 即:
EM = 0×00 || 0×02 || PS || 0×00 || M
3.RSA 加密
a)将EM转换成一个大证书m
m = OS2IP(EM)
b)对公钥(n,e) 和 大整数 m, 使用RSAEP加密原理,产生一个整数密文c
c = RSAEP((n,e0, m)
c)将整数c转换成长度为k的密文串
C = I2OSP(c, k)
4.输出密文C
—————-
解密 RSAES-PKCS1-V1_5-DECRYPT (K, C)
输入: K 接收者的私钥
C 已经加密过的密文串,长度为k (与RSA modulus n的长度一样)
输出: M 消息明文, 长度至多为 k-11
步骤:
长度检查:如果密文C的长度不为k字节(或者 如果 k<11), 输出“decryption error"
2. RSA解密
a. 转换密文C为一个大整数c
c = OS2IP(C)
b. 对RSA私钥(n,d)和密文整数c 实施解密, 产生一个 大整数m
m = RSADP((n,d), c)
如果RSADP输出'ciphertext representative out of range'(意味c>=n), 就输出’decryption error”
c. 转换 m 为长度为k的EM串
EM = I2OSP(m, k)
3. EME-PKCS1-v1_5 解码:将EM分为 非零的PS串 和 消息 M
EM = 0×00 || 0×02 || PS || 0×00 || M
如果EM不是上面给出的格式,或者PS的长度小于8个字节, 那么就输出’decryption error’
5. 输出明文消息M
——————–
签名 RSASSA-PSS-SIGN (K, M)
输入 K 签名者的RSA私钥
M 代签名的消息,一个字节串
输出 S 签名,长度为k的字节串,k是RSA modulus n的字节长度
步骤:
EMSA-PSS encoding: 对消息M实施EMSA-PSS编码操作,产生一个长度为 [(modBits -1)/8]的编码消息EM。 整数 OS2IP(EM)的位长最多是 modBits-1, modBits是RSA modulus n的位长度
EM = EMSA-PSS-ENCODE (M, modBits – 1)
注意:如果modBits-1 能被8整除,EM的字节长比k小1;否则EM字节长为k
2. RSA签名:
a. 将编码后的消息 EM 转换成一个大整数m
m = OS2IP(EM)
b. 对私钥K和消息m 实施 RSASP1 签名,产生一个 大整数s表示的签名
s = RSASP1 (K, m)
c. 把大整数s转换成 长度为k的字串签名S
S = I2OSP(s, k)
3.输出签名S
———–
验证签名 RSASSA-PSS-VERIFY ((n, e), M, S)
输入: (n,e) 签名者的公钥
M 签名者 发来的消息,一个字串
S 待验证的签名, 一个长度为k的字串。k是RSA Modulus n的长度
输出: ’valid signature’ 或者 ‘invalid signature’
步骤:
长度检查: 如果签名S的长度不是k, 输出’invalid signature’
2. RSA验证
a) 将签名S转换成一个大整数s
s = OS2IP (S)
b) 对公钥 (n,e) 和 s 实施 RSAVP1 验证, 产生一个 大整数m
m = RSAVP1 ((n, e), s)
c) 将m 转换成编码的消息EM,长度 emLen = [ (modBits -1)/8 ] 字节。 modBits是RSA modulus n的位长
EM = I2OSP (m, emLen)
注意: 如果 modBits-1可以被8整除,那么emLen = k-1,否则 emLen = k
3. EMSA-PSS验证: 对消息M和编码的EM实施一个 EMSA-PSS验证操作,决定他们是否一致:
Result = EMSA-PSS-VERIFY (M, EM, modBits – 1)
4. 如果Result = “consistent“,那么输出 ”valid signature”
否则, 输出 ”invalid signature”
———–
签名,还可以使用 EMSA-PKCS1-v1_5 encoding编码方法 来产生 EM:
EM = EMSA-PKCS1-V1_5-ENCODE (M, k)
验证签名是,使用 EMSA-PKCS1-v1_5对 M产生第2个编码消息EM’
EM’ = EMSA-PKCS1-V1_5-ENCODE (M, k) .
然后比较 EM和EM’ 是否相同
———————
RSA的加密机制有两种方案一个是RSAES-OAEP,另一个RSAES-PKCS1-v1_5。PKCS#1在新的应用中使用RSAES- OAEP,保留RSAES-PKCS#1-v1_5跟老的应用兼容。它们两的区别仅仅在于加密前编码的方式不同。而加密前的编码是为了提供了抵抗各种活动的敌对攻击的安全机制。
PKCS#1的签名机制也有种方案:RSASSA-PSS和RSASSA-PKCS1-v1_5。同样,RSASSA-PSS用于新的应用而RSASSA-PKCS1-v1_5用于兼容老的应用。
——————–
RSAES-OAEP-ENCRYPT ((n, e), M, L)
选项: Hash 散列函数(hLen 表示 散列函数的输出的字节串的长度)
MGF 掩码生成函数
输入: (n,e) 接收者的RSA公钥(k表示RSA modulus n的字节长度)
M 待加密的消息,一个长度为mLen的字节串 mLen <= k - 2 hLen -2
L 同消息关联的可选的标签,如果不提供L,就采用空串
输出: C 密文,字节长度为k
步骤:
长度检查
a. 如果L的长度超过 hash函数的输入限制(对于SHA-1, 是2^61 -1),输出 label too long
b. mLen > k – 2hLen -2, 输出 message too long
2. EME-OAEP编码
说实话,我看了很久不太懂。。。。。。。
楼主看看下面的代码是不是你所需要的,这是我原来用的时候收集的
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.io.*;
import java.math.BigInteger;
/**
* RSA 工具类。提供加密,解密,生成密钥对等方法。
* 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
* RSA加密原理概述
* RSA的安全性依赖于大数的分解,公钥和私钥都是两个大素数(大于100的十进制位)的函数。
* 据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积
* ===================================================================
* (该算法的安全性未得到理论的证明)
* ===================================================================
* 密钥的产生:
* 1.选择两个大素数 p,q ,计算 n=p*q;
* 2.随机选择加密密钥 e ,要求 e 和 (p-1)*(q-1)互质
* 3.利用 Euclid 算法计算解密密钥 d , 使其满足 e*d = 1(mod(p-1)*(q-1)) (其中 n,d 也要互质)
* 4:至此得出公钥为 (n,e) 私钥为 (n,d)
* ===================================================================
* 加解密方法:
* 1.首先将要加密的信息 m(二进制表示) 分成等长的数据块 m1,m2,...,mi 块长 s(尽可能大) ,其中 2^s<n
* 2:对应的密文是: ci = mi^e(mod n)
* 3:解密时作如下计算: mi = ci^d(mod n)
* ===================================================================
* RSA速度
* 由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论是软件还是硬件实现。
* 速度一直是RSA的缺陷。一般来说只用于少量数据加密。
* 文件名:RSAUtil.java
* @author 赵峰
* 版本:1.0.1
* 描述:本算法摘自网络,是对RSA算法的实现
* 创建时间:2009-7-10 下午09:58:16
* 文件描述:首先生成两个大素数,然后根据Euclid算法生成解密密钥
*/
public class RSAUtil {
//密钥对
private KeyPair keyPair = null;
/**
* 初始化密钥对
*/
public RSAUtil(){
try {
this.keyPair = this.generateKeyPair();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 生成密钥对
* @return KeyPair
* @throws Exception
*/
private KeyPair generateKeyPair() throws Exception {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());
//这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
final int KEY_SIZE = 1024;
keyPairGen.initialize(KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyPairGen.genKeyPair();
return keyPair;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* 生成公钥
* @param modulus
* @param publicExponent
* @return RSAPublicKey
* @throws Exception
*/
private RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) throws Exception {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new Exception(ex.getMessage());
}
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));
try {
return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
} catch (InvalidKeySpecException ex) {
throw new Exception(ex.getMessage());
}
}
/**
* 生成私钥
* @param modulus
* @param privateExponent
* @return RSAPrivateKey
* @throws Exception
*/
private RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) throws Exception {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new Exception(ex.getMessage());
}
RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));
try {
return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
} catch (InvalidKeySpecException ex) {
throw new Exception(ex.getMessage());
}
}
/**
* 加密
* @param key 加密的密钥
* @param data 待加密的明文数据
* @return 加密后的数据
* @throws Exception
*/
public byte[] encrypt(Key key, byte[] data) throws Exception {
try {
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, key);
// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024 加密块大小为127 byte,加密后为128个byte;
// 因此共有2个加密块,第一个127 byte第二个为1个byte
int blockSize = cipher.getBlockSize();
// System.out.println("blockSize:"+blockSize);
int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小
// System.out.println("加密块大小:"+outputSize);
int leavedSize = data.length % blockSize;
// System.out.println("leavedSize:"+leavedSize);
int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
byte[] raw = new byte[outputSize * blocksSize];
int i = 0;
while (data.length - i * blockSize > 0) {
if (data.length - i * blockSize > blockSize)
cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
else
cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
// 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中
// 而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。
i++;
}
return raw;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* 解密
* @param key 解密的密钥
* @param raw 已经加密的数据
* @return 解密后的明文
* @throws Exception
*/
@SuppressWarnings("static-access")
public byte[] decrypt(Key key, byte[] raw) throws Exception {
try {
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE, key);
int blockSize = cipher.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
int j = 0;
while (raw.length - j * blockSize > 0) {
bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
j++;
}
return bout.toByteArray();
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* 返回公钥
* @return
* @throws Exception
*/
public RSAPublicKey getRSAPublicKey() throws Exception{
//获取公钥
RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
//获取公钥系数(字节数组形式)
byte[] pubModBytes = pubKey.getModulus().toByteArray();
//返回公钥公用指数(字节数组形式)
byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();
//生成公钥
RSAPublicKey recoveryPubKey = this.generateRSAPublicKey(pubModBytes,pubPubExpBytes);
return recoveryPubKey;
}
/**
* 获取私钥
* @return
* @throws Exception
*/
public RSAPrivateKey getRSAPrivateKey() throws Exception{
// 获取私钥
RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
// 返回私钥系数(字节数组形式)
byte[] priModBytes = priKey.getModulus().toByteArray();
// 返回私钥专用指数(字节数组形式)
byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();
// 生成私钥
RSAPrivateKey recoveryPriKey = this.generateRSAPrivateKey(priModBytes,priPriExpBytes);
return recoveryPriKey;
}
/**
* 测试
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
RSAUtil rsa = new RSAUtil();
String str = "天龙八部、神雕侠侣、射雕英雄传白马啸西风";
RSAPublicKey pubKey = rsa.getRSAPublicKey();
RSAPrivateKey priKey = rsa.getRSAPrivateKey();
// System.out.println("加密后==" + new String(rsa.encrypt(pubKey,str.getBytes())));
String mw = new String(rsa.encrypt(pubKey, str.getBytes()));
System.out.println("加密后:"+mw);
// System.out.println("解密后:");
System.out.println("解密后==" + new String(rsa.decrypt(priKey,rsa.encrypt(pubKey,str.getBytes()))));
}
}
要求:
输入 必须 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11
如果输入的明文过长,必须切割, 然后填充
输出 和modulus一样长
根据这个要求,对于512bit的密钥, block length = 512/8 – 11 = 53 字节
2) RSA_PKCS1_OAEP_PADDING
RSA_size(rsa) – 41
3)for RSA_NO_PADDING 不填充
RSA_size(rsa)
一般来说, 我们只用RSA来加密重要的数据,比如AES的key, 128bits = 16
加密的输出,总是等于key length
对同样的数据,用同样的key进行RSA加密, 每次的输出都会不一样; 但是这些加密的结果都能正确的解密
—————
预备知识
I2OSP – Integer-to-Octet-String primitive 大整数转换成字节串
I2OSP (x, xLen)
输入: x 待转换的非负整数
xLen 结果字节串的可能长度
————
加密原理 RSAEP ((n, e), m)
输入: (n,e) RSA公钥
m 值为0到n-1 之间一个大整数,代表消息
输出: c 值为0到n-1之间的一个大整数,代表密文
假定: RSA公钥(n,e)是有效的
步骤:
1. 如果m不满足 0 2. 让 c = m^e % n (m的e次幂 除以n ,余数为c)
3. 输出 c
解密原理 RSADP (K, c)
输入: K RSA私钥,K由下面形式:
一对(n,d)
一个五元组(p, q, dP, dQ, qInv)
一个可能为空的三元序列(ri, di, ti), i=3,...,u
c 密文
输出: m 明文
步骤:
1. 如果密文c不满足 0 < c < n-1, 输出 'ciphertext repersentative out of range'
2. 按照如下方法计算m:
a. 如果使用私钥K的第一种形式(n, d), 就让 m = c^d % n (c的d次幂,除以n,余数为m)
b. 如果使用私钥K的第二种像是(p,q, dP, dQ, qInv)和(ri, di, ti),
--------------
----------------
加密 RSAES-PKCS1-V1_5-ENCRYPT ((n, e), M)
输入: (n, e) 接收者的公开钥匙, k表示n所占用的字节长度
M 要加密的消息, mLen表示消息的长度 mLen ≤ k – 11
输出: C 密文, 占用字节数 也为 k
步骤:
1.长度检查, 如果 mLen > k-11, 输出 “message too long”
2. EME-PKCS1-v1_5 编码
a) 生成一个 伪随机非零串PS , 长度为 k – mLen – 3, 所以至少为8, 因为 k-mLen>11
b) 将PS, M,以及其他填充串 一起编码为 EM, 长度为 k, 即:
EM = 0×00 || 0×02 || PS || 0×00 || M
3.RSA 加密
a)将EM转换成一个大证书m
m = OS2IP(EM)
b)对公钥(n,e) 和 大整数 m, 使用RSAEP加密原理,产生一个整数密文c
c = RSAEP((n,e0, m)
c)将整数c转换成长度为k的密文串
C = I2OSP(c, k)
4.输出密文C
—————-
解密 RSAES-PKCS1-V1_5-DECRYPT (K, C)
输入: K 接收者的私钥
C 已经加密过的密文串,长度为k (与RSA modulus n的长度一样)
输出: M 消息明文, 长度至多为 k-11
步骤:
1. 长度检查:如果密文C的长度不为k字节(或者 如果 k<11), 输出“decryption error"
2. RSA解密
a. 转换密文C为一个大整数c
c = OS2IP(C)
b. 对RSA私钥(n,d)和密文整数c 实施解密, 产生一个 大整数m
m = RSADP((n,d), c)
如果RSADP输出'ciphertext representative out of range'(意味c>=n), 就输出’decryption error”
c. 转换 m 为长度为k的EM串
EM = I2OSP(m, k)
3. EME-PKCS1-v1_5 解码:将EM分为 非零的PS串 和 消息 M
EM = 0×00 || 0×02 || PS || 0×00 || M
如果EM不是上面给出的格式,或者PS的长度小于8个字节, 那么就输出’decryption error’
5. 输出明文消息M
——————–
签名 RSASSA-PSS-SIGN (K, M)
输入 K 签名者的RSA私钥
M 代签名的消息,一个字节串
输出 S 签名,长度为k的字节串,k是RSA modulus n的字节长度
步骤:
1. EMSA-PSS encoding: 对消息M实施EMSA-PSS编码操作,产生一个长度为 [(modBits -1)/8]的编码消息EM。 整数 OS2IP(EM)的位长最多是 modBits-1, modBits是RSA modulus n的位长度
EM = EMSA-PSS-ENCODE (M, modBits – 1)
注意:如果modBits-1 能被8整除,EM的字节长比k小1;否则EM字节长为k
2. RSA签名:
a. 将编码后的消息 EM 转换成一个大整数m
m = OS2IP(EM)
b. 对私钥K和消息m 实施 RSASP1 签名,产生一个 大整数s表示的签名
s = RSASP1 (K, m)
c. 把大整数s转换成 长度为k的字串签名S
S = I2OSP(s, k)
3.输出签名S
———–
验证签名 RSASSA-PSS-VERIFY ((n, e), M, S)
输入: (n,e) 签名者的公钥
M 签名者 发来的消息,一个字串
S 待验证的签名, 一个长度为k的字串。k是RSA Modulus n的长度
输出: ’valid signature’ 或者 ‘invalid signature’
步骤:
1. 长度检查: 如果签名S的长度不是k, 输出’invalid signature’
2. RSA验证
a) 将签名S转换成一个大整数s
s = OS2IP (S)
b) 对公钥 (n,e) 和 s 实施 RSAVP1 验证, 产生一个 大整数m
m = RSAVP1 ((n, e), s)
c) 将m 转换成编码的消息EM,长度 emLen = [ (modBits -1)/8 ] 字节。 modBits是RSA modulus n的位长
EM = I2OSP (m, emLen)
注意: 如果 modBits-1可以被8整除,那么emLen = k-1,否则 emLen = k
3. EMSA-PSS验证: 对消息M和编码的EM实施一个 EMSA-PSS验证操作,决定他们是否一致:
Result = EMSA-PSS-VERIFY (M, EM, modBits – 1)
4. 如果Result = “consistent“,那么输出 ”valid signature”
否则, 输出 ”invalid signature”
———–
签名,还可以使用 EMSA-PKCS1-v1_5 encoding编码方法 来产生 EM:
EM = EMSA-PKCS1-V1_5-ENCODE (M, k)
验证签名是,使用 EMSA-PKCS1-v1_5对 M产生第2个编码消息EM’
EM’ = EMSA-PKCS1-V1_5-ENCODE (M, k) .
然后比较 EM和EM’ 是否相同
———————
RSA的加密机制有两种方案一个是RSAES-OAEP,另一个RSAES-PKCS1-v1_5。PKCS#1推荐在新的应用中使用RSAES- OAEP,保留RSAES-PKCS#1-v1_5跟老的应用兼容。它们两的区别仅仅在于加密前编码的方式不同。而加密前的编码是为了提供了抵抗各种活动的敌对攻击的安全机制。
PKCS#1的签名机制也有种方案:RSASSA-PSS和RSASSA-PKCS1-v1_5。同样,推荐RSASSA-PSS用于新的应用而RSASSA-PKCS1-v1_5用于兼容老的应用。
——————–
RSAES-OAEP-ENCRYPT ((n, e), M, L)
选项: Hash 散列函数(hLen 表示 散列函数的输出的字节串的长度)
MGF 掩码生成函数
输入: (n,e) 接收者的RSA公钥(k表示RSA modulus n的字节长度)
M 待加密的消息,一个长度为mLen的字节串 mLen <= k - 2 hLen -2
L 同消息关联的可选的标签,如果不提供L,就采用空串
输出: C 密文,字节长度为k
步骤:
1.长度检查
a. 如果L的长度超过 hash函数的输入限制(对于SHA-1, 是2^61 -1),输出 label too long
b. mLen > k – 2hLen -2, 输出 message too long
2. EME-OAEP编码
说实话,我看了很久不太懂。。。。。。。
1)RSA_PKCS1_PADDING
填充模式,最常用的模式
要求:
输入
必须
比
RSA
钥模长(modulus)
短至少11个字节,
也就是
RSA_size(rsa)
–
11
如果输入的明文过长,必须切割,
然后填充
输出
和modulus一样长
根据这个要求,对于512bit的密钥,
block
length
=
512/8
–
11
=
53
字节
2)
RSA_PKCS1_OAEP_PADDING
RSA_size(rsa)
–
41
3)for
RSA_NO_PADDING
不填充
RSA_size(rsa)
一般来说,
我们只用RSA来加密重要的数据,比如AES的key,
128bits
=
16
加密的输出,总是等于key
length
对同样的数据,用同样的key进行RSA加密,
每次的输出都会不一样;
但是这些加密的结果都能正确的解密
—————
预备知识
I2OSP
–
Integer-to-Octet-String
primitive
大整数转换成字节串
I2OSP
(x,
xLen)
输入:
x
待转换的非负整数
xLen
结果字节串的可能长度
————
加密原理
RSAEP
((n,
e),
m)
输入:
(n,e)
RSA公钥
m
值为0到n-1
之间一个大整数,代表消息
输出:
c
值为0到n-1之间的一个大整数,代表密文
假定:
RSA公钥(n,e)是有效的
步骤:
1.
如果m不满足
0
2.
让
c
=
m^e
%
n
(m的e次幂
除以n
,余数为c)
3.
输出
c
解密原理
RSADP
(K,
c)
输入:
K
RSA私钥,K由下面形式:
一对(n,d)
一个五元组(p,
q,
dP,
dQ,
qInv)
一个可能为空的三元序列(ri,
di,
ti),
i=3,...,u
c
密文
输出:
m
明文
步骤:
1.
如果密文c不满足
0
<
c
<
n-1,
输出
'ciphertext
repersentative
out
of
range'
2.
按照如下方法计算m:
a.
如果使用私钥K的第一种形式(n,
d),
就让
m
=
c^d
%
n
(c的d次幂,除以n,余数为m)
b.
如果使用私钥K的第二种像是(p,q,
dP,
dQ,
qInv)和(ri,
di,
ti),
--------------
----------------
加密
RSAES-PKCS1-V1_5-ENCRYPT
((n,
e),
M)
输入:
(n,
e)
接收者的公开钥匙,
k表示n所占用的字节长度
M
要加密的消息,
mLen表示消息的长度
mLen
≤
k
–
11
输出:
C
密文,
占用字节数
也为
k
步骤:
1.长度检查,
如果
mLen
>
k-11,
输出
“message
too
long”
2.
EME-PKCS1-v1_5
编码
a)
生成一个
伪随机非零串PS
,
长度为
k
–
mLen
–
3,
所以至少为8,
因为
k-mLen>11
b)
将PS,
M,以及其他填充串
一起编码为
EM,
长度为
k,
即:
EM
=
0×00
||
0×02
||
PS
||
0×00
||
M
3.RSA
加密
a)将EM转换成一个大证书m
m
=
OS2IP(EM)
b)对公钥(n,e)
和
大整数
m,
使用RSAEP加密原理,产生一个整数密文c
c
=
RSAEP((n,e0,
m)
c)将整数c转换成长度为k的密文串
C
=
I2OSP(c,
k)
4.输出密文C
—————-
解密
RSAES-PKCS1-V1_5-DECRYPT
(K,
C)
输入:
K
接收者的私钥
C
已经加密过的密文串,长度为k
(与RSA
modulus
n的长度一样)
输出:
M
消息明文,
长度至多为
k-11
步骤:
1.
长度检查:如果密文C的长度不为k字节(或者
如果
k<11),
输出“decryption
error"
2.
RSA解密
a.
转换密文C为一个大整数c
c
=
OS2IP(C)
b.
对RSA私钥(n,d)和密文整数c
实施解密,
产生一个
大整数m
m
=
RSADP((n,d),
c)
如果RSADP输出'ciphertext
representative
out
of
range'(意味c>=n),
就输出’decryption
error”
c.
转换
m
为长度为k的EM串
EM
=
I2OSP(m,
k)
3.
EME-PKCS1-v1_5
解码:将EM分为
非零的PS串
和
消息
M
EM
=
0×00
||
0×02
||
PS
||
0×00
||
M
如果EM不是上面给出的格式,或者PS的长度小于8个字节,
那么就输出’decryption
error’
5.
输出明文消息M
——————–
签名
RSASSA-PSS-SIGN
(K,
M)
输入
K
签名者的RSA私钥
M
代签名的消息,一个字节串
输出
S
签名,长度为k的字节串,k是RSA
modulus
n的字节长度
步骤:
1.
EMSA-PSS
encoding:
对消息M实施EMSA-PSS编码操作,产生一个长度为
[(modBits
-1)/8]的编码消息EM。
整数
OS2IP(EM)的位长最多是
modBits-1,
modBits是RSA
modulus
n的位长度
EM
=
EMSA-PSS-ENCODE
(M,
modBits
–
1)
注意:如果modBits-1
能被8整除,EM的字节长比k小1;否则EM字节长为k
2.
RSA签名:
a.
将编码后的消息
EM
转换成一个大整数m
m
=
OS2IP(EM)
b.
对私钥K和消息m
实施
RSASP1
签名,产生一个
大整数s表示的签名
s
=
RSASP1
(K,
m)
c.
把大整数s转换成
长度为k的字串签名S
S
=
I2OSP(s,
k)
3.输出签名S
———–
验证签名
RSASSA-PSS-VERIFY
((n,
e),
M,
S)
输入:
(n,e)
签名者的公钥
M
签名者
发来的消息,一个字串
S
待验证的签名,
一个长度为k的字串。k是RSA
Modulus
n的长度
输出:
’valid
signature’
或者
‘invalid
signature’
步骤:
1.
长度检查:
如果签名S的长度不是k,
输出’invalid
signature’
2.
RSA验证
a)
将签名S转换成一个大整数s
s
=
OS2IP
(S)
b)
对公钥
(n,e)
和
s
实施
RSAVP1
验证,
产生一个
大整数m
m
=
RSAVP1
((n,
e),
s)
c)
将m
转换成编码的消息EM,长度
emLen
=
[
(modBits
-1)/8
]
字节。
modBits是RSA
modulus
n的位长
EM
=
I2OSP
(m,
emLen)
注意:
如果
modBits-1可以被8整除,那么emLen
=
k-1,否则
emLen
=
k
3.
EMSA-PSS验证:
对消息M和编码的EM实施一个
EMSA-PSS验证操作,决定他们是否一致:
Result
=
EMSA-PSS-VERIFY
(M,
EM,
modBits
–
1)
4.
如果Result
=
“consistent“,那么输出
”valid
signature”
否则,
输出
”invalid
signature”
———–
签名,还可以使用
EMSA-PKCS1-v1_5
encoding编码方法
来产生
EM:
EM
=
EMSA-PKCS1-V1_5-ENCODE
(M,
k)
验证签名是,使用
EMSA-PKCS1-v1_5对
M产生第2个编码消息EM’
EM’
=
EMSA-PKCS1-V1_5-ENCODE
(M,
k)
.
然后比较
EM和EM’
是否相同
———————
RSA的加密机制有两种方案一个是RSAES-OAEP,另一个RSAES-PKCS1-v1_5。PKCS#1推荐在新的应用中使用RSAES-
OAEP,保留RSAES-PKCS#1-v1_5跟老的应用兼容。它们两的区别仅仅在于加密前编码的方式不同。而加密前的编码是为了提供了抵抗各种活动的敌对攻击的安全机制。
PKCS#1的签名机制也有种方案:RSASSA-PSS和RSASSA-PKCS1-v1_5。同样,推荐RSASSA-PSS用于新的应用而RSASSA-PKCS1-v1_5用于兼容老的应用。
——————–
RSAES-OAEP-ENCRYPT
((n,
e),
M,
L)
选项:
Hash
散列函数(hLen
表示
散列函数的输出的字节串的长度)
MGF
掩码生成函数
输入:
(n,e)
接收者的RSA公钥(k表示RSA
modulus
n的字节长度)
M
待加密的消息,一个长度为mLen的字节串
mLen
<=
k
-
2
hLen
-2
L
同消息关联的可选的标签,如果不提供L,就采用空串
输出:
C
密文,字节长度为k
步骤:
1.长度检查
a.
如果L的长度超过
hash函数的输入限制(对于SHA-1,
是2^61
-1),输出
label
too
long
b.
mLen
>
k
–
2hLen
-2,
输出
message
too
long
2.
EME-OAEP编码
说实话,我看了很久不太懂。。。。。。。
简单点说pkcs1中的填充就是【00 01+若干ff+00+明文数据】总长度为模长,例如rsa1024为128字节。
还是实际搞个rsa1024例子吧
00 01 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF 00 30 21 30
09 06 05 2B 0E 03 02 1A 05 00 04 14 EC A2 4D 06
CE 34 6A A8 4E E5 61 E2 D4 4A D9 9F A4 0A 47 34
最后的为实际数据
30 21 30
09 06 05 2B 0E 03 02 1A 05 00 04 14 EC A2 4D 06
CE 34 6A A8 4E E5 61 E2 D4 4A D9 9F A4 0A 47 34
A Practical Guide To Quantitative Finance Interviews 电子版...
id=RosxmAYFFosC&printsec=frontcover&dq=A+Practical+Guide+To+Quantitative+Finance+Interviews&source=bl&ots=yzZU63kiai&sig=mkpKCsfIPb59AiItyLRWSheXGck&hl=zh-CN&ei=7lIcTe-4MMKblgfg0cDtCw&sa=X&oi=book_result&ct=result&resnum=1&ved=0CBkQ6AEwAA#v=onepage&q&f=false ...
禄柿武都: RSA是一种块加密的算法,所以对于明文需要将他们分成固定的块长度,考虑到输入的数据长度的问题,所以加解密的填充有好几种:1. 无填充,就是直接对明文进行加密2. PKCS1.将数据长度分成密钥长度-11byte,比如密钥是1024bit,那么...
永济市13739816455: pkcs1签名和pkcs7签名的区别 - ?
禄柿武都: 定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封[22].
永济市13739816455: Android中自带的RSA加密算法和JAVA中的不是一个标准的吗? - ?
禄柿武都: 有点区别,java中默认填充方式是RSA/ECB/PKCS1Padding,Cipher.getInstance("RSA/ECB/PKCS1Padding");android不是
永济市13739816455: 攻击者如何利用已有的签名方案对RSA签名攻击? - ?
禄柿武都: 简单来说:利用RSA签名的生成与解密流程进行相关欺骗以达成攻击的目的 以下内容来自CSDN RSA算法的签名和验签操作本质上来讲也是大数的模幂运算,RSA算法的安全性很大程度上取决于填充方式,因此在一个安全的RSA加密操作需要选择一个合适的填充模式,因此签名的运算同样需要选择合适的padding方式.主要有两种padding方式PKCS_V15PKCS_V21(PSS)验签是签名的逆运算,在理解了签名操作之前再来看验签是非常容易的.验签操作会调用如下的mbedtls_rsa_pkcs1_verify函数,此函数制作一件事,就是根据ctx-->padding的类型来选择对应的验签函数.有兴趣的话建议自行查询(涉及专业领域)
永济市13739816455: android和java webservice RSA处理的不同?
禄柿武都: android和java webservice RSA处理的不同 1.andorid机器上生成的(密钥对由服务器在windows xp下生成并将公钥发给客户端保存)密码无法在服务器通过私钥解密. 2.为了测试,在服务器本地加解密正常,另外,在android上加解密也正常,...
永济市13739816455: 如何使用javascript进行RSA/ECB/PKCS1Padding算法加密 - ?
禄柿武都: javascript rsa加密/java使用Cipher.getInstance("RSA/ECB/PKCS1Padding")解密 1)服务器端获得生成密钥对; 2)javascript使用公钥加密; 3)java获得密文使用私钥解密;
永济市13739816455: Android中自带的RSA加密算法和JAVA中的不是一个标准的吗?
禄柿武都: 有点区别,java中默认填充方式是RSA/ECB/PKCS1Padding,Cipher.getInstance("RSA/ECB/PKCS1Padding");android不是 java Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); android Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
永济市13739816455: 在Python3中,已知一个公钥,如何使用这个公钥加密json数据 - ?
禄柿武都: 你好,你这个是非对称加密算法,利用公钥加密然后用私钥解密.目前用的多是Rsa和椭圆加密算法,目前爬虫上面用的比较多都是Rsa算法.下面是python的rsa加密代码,你可以参考一下 from Crypto.Cipher import PKCS1_v1_5 as Cipher_...
永济市13739816455: 几种加密算法在java中的应用?
禄柿武都: 简单的Java加密算法有:第一种. BASEBase是网络上最常见的用于传输Bit字节代码的编码方式之一,大家可以查看RFC~RFC,上面有MIME的详细规范.Base编码可用于在HTTP环境下传递较长的标识信息.例如,在Java Persistence系统...
永济市13739816455: 求用OpenSSL做的RSA文件加密程序实例,VC++6.0的,各位大侠帮帮忙,急用呀,多谢啦 - ?
禄柿武都: #include <openssl/rsa.h> #include <openssl/sha.h> int main() { RSA *r; int bits=1024,ret,len,flen,padding,i; unsigned long e=RSA_3; BIGNUM *bne; unsigned char*key,*p; BIO *b; unsigned charfrom[500],to[500],out[500]; bne=BN_new(); ret=BN_set...