使用公钥validation签名

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

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

-----BEGIN PUBLIC KEY----- ........................................ -----END PUBLIC KEY----- 

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

这是我的算法:

 // 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方法,它就可以完成所有工作。