Java 给定公共指数和模的RSA签名验证
尝试使用Sun JCE和来自CAVP程序的测试向量对签名验证进行编码 我得到了公钥指数和模,以及消息和签名。我做了以下工作:Java 给定公共指数和模的RSA签名验证,java,rsa,digital-signature,Java,Rsa,Digital Signature,尝试使用Sun JCE和来自CAVP程序的测试向量对签名验证进行编码 我得到了公钥指数和模,以及消息和签名。我做了以下工作: private static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes, int saltlen) throws Exception {
private static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes, int saltlen) throws Exception
{
Signature sig = Signature.getInstance(algo);
KeyFactory keyMaker = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
new BigInteger(modulus),
new BigInteger(exponent));
RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);
System.out.println("algorithm is " + algo);
sig.initVerify(pubKey);
Utils.outputValue("n", modulus, modulus.length, System.out, false);
Utils.outputValue("e", exponent, exponent.length, System.out, false);
Utils.outputValue("Msg", message, message.length, System.out, false);
Utils.outputValue("S", sigBytes, sigBytes.length, System.out, false);
BigInteger Nvalue = pubKey.getPublicExponent();
Utils.outputValue("key value of n", Nvalue.toByteArray(), System.out, false);
BigInteger Evalue=pubKey.getModulus();
Utils.outputValue("key value of e", Evalue.toByteArray(), System.out, false);
sig.update(message);
if(sig.verify(sigBytes))
oPS.println("Result = P");
else
oPS.println("Result = F");
。
.
算法类似于“SHA1withRSA”,我构建了公钥,如图所示。当我从键本身列出得到的模数和指数时,它们已反转
n=009DE541C71A95389D9E8619EA1D6E2C69ED6C703701E518351676022AB98395D6B35A38B024F92BCE6DD1C5BE9D51DFFD1687D19DCEE73F2C73E443695523125F6E360BA844623110E65932FE069BED42C5BF88141828BDADA3796184870CB8CF3019DA264E5639ECCF7224D43AD788B40A4042AA790E946F
e=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
Msg=64B13DF4B008CCD5CE146018481C2568BBE2B93EC658D1C7F4AD734592CD65B3BE2BE5A7C1BE9A7D9F49CBB2ECE0EE0A8C406AEDE84E0121BD51829D6E083862AE5B282D92C19D3923F70616F565A5213572116F91A85FF5F4E6AD2E31C15C97F3266AF1957414C4FD2A4143FB80CC2B9FA7B20239A17135
S=5B4458F6AEFF91C4699EE9BDF8757987FB8DB229814A2992945AC53BCF19B9179E53CFED258726D205107AC000D41E570FE8C4FB321FC9B4B5469C60CD2032195F314BA6E6B0B30A51C9834242DAA15EC903801068E782EA164BA5D884EFE720E9DD63618B82341247F991A6DAA21BD62BDC737D8A20E5
n=03的键值
e=009DE541C71A95389D9E8619EA1D6E2C69ED6C703701E518351676022AB98395D6B35A38B024F92BCE6DD1C5BE9D51DFFD1687D19DCEE73F2C73E443695523125F6E360BA84462311E10E65932FE069BED42C5BF88141828BDAD3796184870CB8CF3019DA264E5639ECCF7224D4AD788B40A4042AA790E946F
这些测试中有些应该失败,但有些应该成功。没有正确验证。。。有什么想法吗?谢谢
下面是应用程序,后面是一组示例输入
package cavp.rsa;
import cavp.*;
import java.io.*;
import java.security.KeyFactory;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.security.PublicKey;
import java.util.Date;
import java.math.BigInteger;
public class RSASigVerify
{
private static boolean verboseFlag=false;
public static void main(String[] args) throws Exception
{
String requestFile;
String responseFile;
int saltLen=-1;
int argstart=0;
if(args.length < 2)
throw new Exception("missing parameters");
if(args.length == 3) {
if(args[0].equals("-saltlen")) {
saltLen=Integer.parseInt(args[1]);
if(saltLen < 0)
throw new Exception("bad -saltlen parameter ");
argstart=2;
} else {
if(args[0].equals("-x931")) {
saltLen=-2;
argstart=1;
}
} else {
if(args.length > 3)
throw new Exception("invalid invocation");
}
requestFile=args[argstart];
responseFile=args[argstart+1];
if(processFile(requestFile, responseFile, saltLen))
System.out.println("Failed to process file " + requestFile);
else
System.out.println("Processing complete for " + requestFile);
}
private static boolean processFile(String rqfn, String rspfn, int saltLen) throws Exception
{
File inFile = new File(rqfn), outFile = new File(rspfn);
if(!inFile.exists() || !inFile.isFile() || !inFile.canRead()) {
System.out.println("Bad input File " + rqfn);
return true;
}
FileReader inFR = new FileReader(inFile);
BufferedReader inBR = new BufferedReader(inFR);
PrintStream outPS = new PrintStream(outFile);
String input, keyword, value, digestType=null;
int p, v, q, i, lnum=0;
byte[] Msg=null, nBytes=null, eBytes=null, sigBytes=null;
boolean msgFound=false, nFound=false, eFound=false, sigFound=false;
try {
while((input = inBR.readLine()) != null ) {
lnum++;
if((p = input.indexOf('=')) < 0) {
outPS.println(input);
continue;
}
if(input.charAt(p-1) == ' ')
keyword=input.substring(0,p-1);
else
keyword=input.substring(0, p);
p++;
for(i=p; i<input.length(); i++) {
if(input.charAt(i) == ' ')
p++;
else
break;
}
if((v = input.indexOf('\n')) > 0) {
for(q=v-1; q>p+1; q--) {
if(input.charAt(q) != ' ')
break;
}
} else {
if((v = input.indexOf(' ', p)) > 0) {
q=v-1;
} else {
q=input.length();
}
}
value=input.substring(p,q);
if(keyword.indexOf("n") >= 0) {
nBytes=Utils.hexStringToByteArray(value);
if(nBytes.length <= 0) {
System.out.println("bad value for modulus");
return true;
}
nFound=true;
} else {
if(keyword.equals("e")) {
eBytes=Utils.hexStringToByteArray(value);
if(eBytes.length <= 0) {
System.out.println("bad value for private exponent");
return true;
}
eFound=true;
} else {
if(keyword.equals("SHAAlg")) {
if(!value.equals("SHA1") && !value.equals("SHA224") && !value.equals("SHA256") && !value.equals("SHA384") &&
!value.equals("SHA512")) {
System.out.println("Bad SHAAlg parameter " + input);
return true;
}
digestType=value + "withRSA";
} else {
if(keyword.equals("Msg")) {
if(msgFound) {
System.out.println("more than one Msg found");
return true;
} else
msgFound=true;
String tempMsg;
if((value.length() & 0x01) != 0) {
tempMsg="0" + value;
} else {
tempMsg=value;
}
Msg=Utils.hexStringToByteArray(tempMsg);
if(Msg.length <= 0) {
System.out.println("bad Msg parameter");
return true;
}
} else {
if(keyword.equals("S")) {
sigBytes=Utils.hexStringToByteArray(value);
if(sigBytes.length <= 0) {
System.out.println("bad signature parameter");
return true;
}
sigFound=true;
} else {
if(keyword.equals("Result")) {
continue;
}
}
}
}
}
}
outPS.println(input);
if(digestType != null && msgFound && nFound && eFound && sigFound) {
if(verifySignature(digestType, outPS, Msg, nBytes, eBytes, sigBytes, saltLen)) {
throw new Exception("error in digest generator");
}
msgFound=false;
eFound=false;
sigFound=false;
}
}
} catch( FileNotFoundException e) {
System.out.println("error processing file");
}
inFR.close();
outPS.close();
return false;
}
private static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes, int saltlen) throws Exception
{
// yet to implement saltLen == -2 for X9.31 padding
// saltLen >= 0 for PSS Signatures
Signature sig = Signature.getInstance(algo);
KeyFactory keyMaker = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
new BigInteger(modulus),
new BigInteger(exponent));
RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);
System.out.println("algorithm is " + algo);
sig.initVerify(pubKey);
sig.update(message);
if(sig.verify(sigBytes))
oPS.println("Result = P");
else
oPS.println("Result = F");
return false;
}
}
下面是一个向量文件,它应该传递:
# CAVS 11.5
# "SigVer PKCS#1 Ver 1.5" information for
# Mod sizes selected: 1024 2048
# SHA Algorithm selected:SHA1 SHA256
# Generated on Mon Nov 28 14:03:58 2011
[mod = 1024]
n = 9de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f
SHAAlg = SHA1
e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
Msg = fe196459e8232a9f94e8c93d88ddae7d38be7a10e2dd03ffb7bb9be43bd59659eec006b12c78c9e652f6c6d3220073a369459b8adea95eb34ede7979f634c7d931b208275365e201d4f82582b18553b70fab605721e1b6ae4d097cdb8a49183b0d16f22524917bd862176fb1fc1357a2731751df732c13dafc662e72bfbb9067
S = 94af4ce7f323d1bf4904a673d2884e30a55a108c44e4eb2bfc0a0f061f46fefe23fe74c760e947bd1fbf1bb1a30d66b3d7dccfb425d3a6551dd444f90d4f06c3e0da6dc3c7a45e062b08d24553f0091acae47ffaae495e13da66308dd9e0be87e2b960ab823f83e55815b66a1076ab238cc3883cbf7312521d0988214bb07d96
你的密码是:
BigInteger Nvalue = pubKey.getPublicExponent();
N是关键模数,而不是公共指数。您的文本标签和变量内容不匹配
您的签名验证问题可能是其他问题。您是否收到错误消息,或者
verify()
方法只返回false
?我已经更新了答案。我说你的样品不起作用是不对的,因为签名和信息一样长。事实上,由于RSA加密是在SHA-1计算之后进行的,因此最终签名的长度可达n字节,其中n是模的大小n
所以,据我所知,你可能一点问题都没有。你确定你贴的样品是阳性的吗?如果是,您确定它是使用SHA1withRSA
算法创建的吗
下面我已经包含了基于您的代码的示例Groovy代码。代码基本上创建一个签名并对其进行验证。我从网站上获得了公钥和私钥对,但任何密钥对都可以工作。代码是自我解释的,所以我将总结一下签名应该如何工作,以防您希望使用随机密钥对和消息进行测试和验证
javax.crypto.BadPaddingException:如果模数为负(第一位设置为2的补码),则消息大于模数异常,因此我必须在左边附加1字节的零
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
byte[] modulus = Utils.getBytes("00d94d889e88853dd89769a18015a0a2e6bf82bf356fe14f251fb4f5e2df0d9f9a94a68a30c428b39e3362fb3779a497eceaea37100f264d7fb9fb1a97fbf621133de55fdcb9b1ad0d7a31b379216d79252f5c527b9bc63d83d4ecf4d1d45cbf843e8474babc655e9bb6799cba77a47eafa838296474afc24beb9c825b73ebf549");
byte[] publicExp = Utils.getBytes("010001");
byte[] privateExp = Utils.getBytes("047b9cfde843176b88741d68cf096952e950813151058ce46f2b048791a26e507a1095793c12bae1e09d82213ad9326928cf7c2350acb19c98f19d32d577d666cd7bb8b2b5ba629d25ccf72a5ceb8a8da038906c84dcdb1fe677dffb2c029fd8926318eede1b58272af22bda5c5232be066839398e42f5352df58848adad11a1");
byte[] message = Utils.getBytes("00");
byte[] signature;
signature = createSignature("SHA1withRSA", System.out, message, modulus, privateExp, signature);
println ((new BigInteger(signature)).toString(16));
verifySignature("SHA1withRSA", System.out, message, modulus, publicExp, signature);
public static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes) throws Exception
{
Signature sig = Signature.getInstance(algo);
KeyFactory keyMaker = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);
sig.initVerify(pubKey);
sig.update(message);
return sig.verify(sigBytes);
}
public static byte[] createSignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes) throws Exception
{
Signature sig = Signature.getInstance(algo);
KeyFactory keyMaker = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(exponent));
RSAPrivateKey privKey = (RSAPrivateKey)keyMaker.generatePrivate(privKeySpec);
sig.initSign(privKey);
sig.update(message);
return sig.sign();
}
class Utils{
private static char[] lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
public static void outputValue(String s, byte[] data, int length, PrintStream out, boolean wtf){
out.print(s+" = ");
for(int i=0;i<length;i++){
out.print(lookup[(data[i] >> 4) & 0xF]);
out.print(lookup[data[i] & 0xF]);
}
out.println();
}
public static byte[] getBytes(String s){
byte[] result = new byte[s.length()>>1];
for(int i=0;i<result.length;i++){
result[i] = Integer.parseInt(s.substring(i*2, i*2+2), 16);
}
return result;
}
}
导入java.security.*;
导入java.security.interfaces.*;
导入java.security.spec.*;
byte[]module=Utils.getBytes(“00D94D889E88853DD89769A18015A0A2E6BF82BF356FE14F251FB4F5E2DF0D9A94A68A30C428B39E3362FB3779A497ECEAA37100F264D7FB9FB1A97FBF621133DE5FDCB9B1AD0D7A31B37916D79F52527B9B63D83D4ECF45CD15C57B843E74BABC55E9BB67997B7A47B7349”);
byte[]publicExp=Utils.getBytes(“010001”);
byte[]privateExp=Utils.getBytes(“047B9CFDE843176B88741D68CF096952E950813151058CE46F2B048791A26E507A10957793C12BAE1E09D82213AD9326928CF7C2350ACB19C98F19D32D577D666CD7BB8B2B629D25CF72A5CEB8A8DA038906C84DCDB1FE677DFFB2C029FD8926318EEDEB1B5872AF22BDC5232BE0683932FE45352DF588ADADD11A1”);
字节[]消息=Utils.getBytes(“00”);
字节[]签名;
签名=createSignature(“SHA1withRSA”、System.out、消息、模数、privateExp、签名);
println((新的BigInteger(签名)).toString(16));
验证签名(“SHA1withRSA”、System.out、消息、模数、publicExp、签名);
公共静态布尔验证签名(字符串算法、打印流操作、字节[]消息、字节[]模、字节[]指数、字节[]sigBytes)引发异常
{
Signature sig=Signature.getInstance(algo);
KeyFactory keyMaker=KeyFactory.getInstance(“RSA”);
RSAPublicKeySpec pubKeySpec=新的RSAPublicKeySpec(新的BigInteger(模数)、新的BigInteger(指数));
RSAPublicKey pubKey=(RSAPublicKey)keyMaker.generatePublic(pubKeySpec);
sig.initVerify(pubKey);
信号更新(信息);
返回sig.verify(sigBytes);
}
公共静态字节[]createSignature(字符串algo、打印流操作、字节[]消息、字节[]模数、字节[]指数、字节[]sigBytes)引发异常
{
Signature sig=Signature.getInstance(algo);
KeyFactory keyMaker=KeyFactory.getInstance(“RSA”);
RSAPrivateKeySpec privKeySpec=新的RSAPrivateKeySpec(新的BigInteger(模数)、新的BigInteger(指数));
RSAPrivateKey privKey=(RSA)
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
byte[] modulus = Utils.getBytes("00d94d889e88853dd89769a18015a0a2e6bf82bf356fe14f251fb4f5e2df0d9f9a94a68a30c428b39e3362fb3779a497eceaea37100f264d7fb9fb1a97fbf621133de55fdcb9b1ad0d7a31b379216d79252f5c527b9bc63d83d4ecf4d1d45cbf843e8474babc655e9bb6799cba77a47eafa838296474afc24beb9c825b73ebf549");
byte[] publicExp = Utils.getBytes("010001");
byte[] privateExp = Utils.getBytes("047b9cfde843176b88741d68cf096952e950813151058ce46f2b048791a26e507a1095793c12bae1e09d82213ad9326928cf7c2350acb19c98f19d32d577d666cd7bb8b2b5ba629d25ccf72a5ceb8a8da038906c84dcdb1fe677dffb2c029fd8926318eede1b58272af22bda5c5232be066839398e42f5352df58848adad11a1");
byte[] message = Utils.getBytes("00");
byte[] signature;
signature = createSignature("SHA1withRSA", System.out, message, modulus, privateExp, signature);
println ((new BigInteger(signature)).toString(16));
verifySignature("SHA1withRSA", System.out, message, modulus, publicExp, signature);
public static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes) throws Exception
{
Signature sig = Signature.getInstance(algo);
KeyFactory keyMaker = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);
sig.initVerify(pubKey);
sig.update(message);
return sig.verify(sigBytes);
}
public static byte[] createSignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes) throws Exception
{
Signature sig = Signature.getInstance(algo);
KeyFactory keyMaker = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(exponent));
RSAPrivateKey privKey = (RSAPrivateKey)keyMaker.generatePrivate(privKeySpec);
sig.initSign(privKey);
sig.update(message);
return sig.sign();
}
class Utils{
private static char[] lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
public static void outputValue(String s, byte[] data, int length, PrintStream out, boolean wtf){
out.print(s+" = ");
for(int i=0;i<length;i++){
out.print(lookup[(data[i] >> 4) & 0xF]);
out.print(lookup[data[i] & 0xF]);
}
out.println();
}
public static byte[] getBytes(String s){
byte[] result = new byte[s.length()>>1];
for(int i=0;i<result.length;i++){
result[i] = Integer.parseInt(s.substring(i*2, i*2+2), 16);
}
return result;
}
}