JAVA中的签名验证和签名长度
Posted
技术标签:
【中文标题】JAVA中的签名验证和签名长度【英文标题】:Signature Verification in JAVA and Signature Length 【发布时间】:2018-09-18 19:30:05 【问题描述】:我开发了一个java应用程序,它从PEM文件中读取公钥,然后验证签名。我从外部(一家公司)收到了这个签名,它是使用 RSA2048 生成的。但是我收到以下错误消息:
“签名长度不正确:得到 384 但预期为 256。”
在验证之前我必须对这个签名做一些修改吗?
package read_key_pck;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class Main
//protected final static Logger LOGGER = Logger.getLogger(Main.class);
public final static String RESOURCES_DIR = "C:\\Users\\KX5710\\eclipse-workspace\\read_key\\src\\read_key_pck\\";
public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception
Signature publicSignature = Signature.getInstance("SHA256withRSA");
publicSignature.initVerify(publicKey);
publicSignature.update(plainText.getBytes(UTF_8));
byte[] signatureBytes = Base64.getDecoder().decode(signature);
return publicSignature.verify(signatureBytes);
public static void main(String[] args) throws Exception
Security.addProvider(new BouncyCastleProvider());
PublicKey pub = null;
KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
try
/*PrivateKey priv = generatePrivateKey(factory, RESOURCES_DIR
+ "id_rsa");*/
pub = generatePublicKey(factory, RESOURCES_DIR
+ "rsa_2048_pub.pem");
catch (InvalidKeySpecException e)
e.printStackTrace();
String encodedPublicKey = Base64.getEncoder().encodeToString(pub.getEncoded());
System.out.println("publickey: " + encodedPublicKey);
boolean isCorrect = verify(" 5 5.00 1.80", "12c1d454cde1c3ca07f179fc3c8d1e739b482b0447cd2c60342455a10db15ee8657e73e7f9195f7e33d93db8fc1cda236d41bf2a804be0f860c16ebf952c02e89f254a19daf54b66d1383ebe5aaf049e7c48ecd33a98f771165cb8b7b0323d81508c6260109c8f622655f363bbf638802d92c985e8ab982eebc7167c979cde4755b7afcc880e32118c3e6b72eecbd0ebf680da84a59c8cc523051c3a8ec12595ec6bdc0856b9faf9562919c315e78655c8f35f759899f27d729e56a96ec8bd85fe6221441dd91f9facd5f5eadcb4b7fac08a9ddab29f18d353e6762e0769068077fea7bc94d6df405a86c9e98096e8e50e59ec7263ce6c4e88bb96ab3c663baa", pub);
System.out.println("Signature verification: " + isCorrect);
private static PublicKey generatePublicKey(KeyFactory factory,
String filename) throws InvalidKeySpecException,
FileNotFoundException, IOException
PemFile pemFile = new PemFile(filename);
byte[] content = pemFile.getPemObject().getContent();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
return factory.generatePublic(pubKeySpec);
package read_key_pck;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
public class PemFile
private PemObject pemObject;
public PemFile(String filename) throws FileNotFoundException, IOException
PemReader pemReader = new PemReader(new InputStreamReader(
new FileInputStream(filename)));
try
this.pemObject = pemReader.readPemObject();
finally
pemReader.close();
public PemObject getPemObject()
return pemObject;
【问题讨论】:
您的签名被编码为 HEX 而不是 BASE64。将byte[] signatureBytes = Base64.getDecoder().decode(signature);
更改为byte[] signatureBytes = DatatypeConverter.parseHexBinary(signature)
@pedrofb 谢谢,现在可以了。
@pedrofb 您应该将其发布为答案,而不是评论 - 然后它可以被正确地投票并标记为已接受。
【参考方案1】:
您的签名被编码为 HEX 而不是 BASE64。 改变
byte[] signatureBytes = Base64.getDecoder().decode(signature);
与
byte[] signatureBytes = DatatypeConverter.parseHexBinary(signature)
【讨论】:
以上是关于JAVA中的签名验证和签名长度的主要内容,如果未能解决你的问题,请参考以下文章
验证openssl c ++中的签名,该签名由JAVA DSA签名?