java 公钥 验签 xml_java – 使用公钥验证签名

本文介绍了如何在Java中通过公钥验证XML消息的签名。文章详细展示了从读取公钥文件到使用Signature类进行验证的完整过程,解决了InvalidKeySpecException的问题,利用BouncyCastle库解析PEM格式的公钥。
摘要由CSDN通过智能技术生成

我有一个外部服务,在一些已定义的事件后给我回电话,并用其私钥签署他的请求.

我存储了公钥,看起来像:

-----BEGIN PUBLIC KEY-----

........................................

-----END PUBLIC KEY-----

所以我的工作是通过验证签名来检查请求的内容是否未被更改.

这是我的算法:

// 1 - reading public key :

Scanner scanner = new Scanner( new File( keyPath ) );

// encodedPublicKey.toString( );

StringBuilder sb = new StringBuilder( );

while ( scanner.hasNextLine( ) )

{

sb.append( scanner.nextLine( ) );

sb.append( '\n' );

}

byte[] encodedPublicKey = sb.toString( ).getBytes( "utf-8" );

// 2 - loading public key in a relevant object :

X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( publicKeyBytes );

KeyFactory keyFactory = KeyFactory.getInstance( "DSA" );

PublicKey publicKey = keyFactory.generatePublic( publicKeySpec );

// 3 - verifying content with signature and content :

Signature sig = Signature.getInstance( "SHA1withDSA" );

sig.initVerify( publicKey );

sig.update( message.getBytes( ) );

ret = sig.verify( sign.getBytes( ) );

但是现在我的算法通过以下消息停止在“PublicKey publicKey = keyFactory.generatePublic(publicKeySpec)”步骤:

java.security.spec.InvalidKeySpecException: Inappropriate key specification: invalid key format

那么如何以java api接受的方式加载我的密钥呢?

解决方法:

其实我找到了解决方案.

问题是以正确的方式加载公钥文件.

我把bouncycastle库添加到我的依赖项:

org.bouncycastle

bcprov-jdk15on

1.47

它提供PemReader,允许读取和加载非认证的公钥.

这是我的实用工具类:

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.io.UnsupportedEncodingException;

import java.net.URLDecoder;

import java.security.InvalidKeyException;

import java.security.KeyFactory;

import java.security.NoSuchAlgorithmException;

import java.security.PublicKey;

import java.security.Signature;

import java.security.SignatureException;

import java.security.spec.InvalidKeySpecException;

import java.security.spec.X509EncodedKeySpec;

import org.bouncycastle.util.io.pem.PemReader;

import org.castor.util.Base64Decoder;

import fr.paris.lutece.portal.service.util.AppLogService;

/**

* Classe d'aide à l'interfacage avec le service paybox.

*

* Toutes les informations parameterables sont sous la forme paybox.*

*/

public final class PayboxUtil

{

/** The Constant CHARSET. */

private static final String CHARSET = "utf-8";

/** The Constant ENCRYPTION_ALGORITHM. */

private static final String ENCRYPTION_ALGORITHM = "RSA";

/** The Constant HASH_ENCRIPTION_ALGORITHM. */

private static final String HASH_ENCRYPTION_ALGORITHM = "SHA1withRSA";

/**

* constructeur privé pour classe statique.

*/

private PayboxUtil( )

{

}

/**

* Controle si une signature est bien celle du message à l'aide de la clé

* publique de l'emmeteur?.

*

* @param message le message

* @param sign la signature

* @param keyPath le chemin vers la clé publique.

* @return true si la signature est bien celle du message avec la clé privé

* attendue.

*/

public static boolean checkSign( String message, String sign, String keyPath )

{

boolean ret = false;

try

{

ret = PayboxUtil.verify( message, sign, PayboxUtil.getKey( keyPath ) );

}

catch ( final FileNotFoundException e )

{

AppLogService.error( e );

}

catch ( final IOException e )

{

AppLogService.error( e );

}

catch ( final NoSuchAlgorithmException e )

{

AppLogService.error( e );

}

catch ( final InvalidKeySpecException e )

{

AppLogService.error( e );

}

catch ( final InvalidKeyException e )

{

AppLogService.error( e );

}

catch ( final SignatureException e )

{

AppLogService.error( e );

}

return ret;

}

/**

* Récupère la clé publique à partir du chemin passé en paramètre.

*

* @param keyPath le chemin vers la clé.

* @return la clé publique

* @throws NoSuchAlgorithmException the no such algorithm exception

* @throws IOException Signals that an I/O exception has occurred.

* @throws InvalidKeySpecException the invalid key spec exception

*/

private static PublicKey getKey( String keyPath )

throws NoSuchAlgorithmException, IOException, InvalidKeySpecException

{

final KeyFactory keyFactory = KeyFactory.getInstance( PayboxUtil.ENCRYPTION_ALGORITHM );

final PemReader reader = new PemReader( new FileReader( keyPath ) );

final byte[] pubKey = reader.readPemObject( ).getContent( );

final X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( pubKey );

return keyFactory.generatePublic( publicKeySpec );

}

/**

* effectue la vérification du message en fonction de la signature et de la

* clé.

*

* @param message le message

* @param sign la signature

* @param publicKey la clé publique.

* @return true, if successful

* @throws NoSuchAlgorithmException the no such algorithm exception

* @throws InvalidKeyException the invalid key exception

* @throws SignatureException the signature exception

* @throws UnsupportedEncodingException the unsupported encoding exception

*/

private static boolean verify( String message, String sign, PublicKey publicKey )

throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException

{

final Signature sig = Signature.getInstance( PayboxUtil.HASH_ENCRYPTION_ALGORITHM );

sig.initVerify( publicKey );

sig.update( message.getBytes( PayboxUtil.CHARSET ) );

final byte[] bytes = Base64Decoder.decode( URLDecoder.decode( sign, PayboxUtil.CHARSET ) );

return sig.verify( bytes );

}

}

您只需将签名内容,签名和密钥路径传递给checkSign方法,它就可以完成所有工作.

标签:verify,java,public-key

来源: https://codeday.me/bug/20190930/1836971.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值