使用公钥验证签名

我有一个外部服务,在定义的事件发生后会给我回电,并用其私钥签署他的请求。

我已经存储了如下公钥:

-----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库添加到我的依赖项中:

<dependency>

<groupId>org.bouncycastle</groupId>

<artifactId>bcprov-jdk15on</artifactId>

<version>1.47</version>

</dependency>

它提供了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方法即可完成所有工作。

以上是 使用公钥验证签名 的全部内容, 来源链接: utcz.com/qa/413874.html

回到顶部