How to RSA verify signature in java that was generated in php

We use phpseclib to publicly access data keys, and android java is used to verify the public key. But it didn’t work again.

PHP code For generating keys and signing with a private key

include_once("phpseclib/autoload.php"); function getKeys($keysize=2048){ $rsa = new Crypt_RSA(); //$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_OPENSSH); //$rsa->setPublicKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1); $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8); $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); $d = $rsa->createKey($keysize); return array("publickey"=>$d['publickey'], "privatekey"=>$d['privatekey']); } function encryptdata($message, $encryptionKey){ $rsa = new Crypt_RSA(); //$rsa->setPublicKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1); $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8); $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); //$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_OPENSSH); $rsa->loadKey($encryptionKey); // public key return $rsa->encrypt($message); } function decryptdata($message, $decryptionKey){ $rsa = new Crypt_RSA(); // $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_OPENSSH); // $rsa->setPublicKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1); $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8); $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); $rsa->loadKey($decryptionKey); // private key return $rsa->decrypt($message); } $keys = getKeys(); file_put_contents("key.pub", $keys["publickey"]); file_put_contents("key.priv", $keys["privatekey"]); $publickey = file_get_contents("key.pub"); $privatekey = file_get_contents("key.priv"); //print_r($keys); $string = "Hi I m here"; $hash = hash("sha256", $string); $encdata = encryptdata($hash, $privatekey); echo $base_encdata = base64_encode($encdata); 

JAVA Code

 import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Base64; import java.security.spec.X509EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.KeyFactory; import java.security.Signature; import java.security.PublicKey; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.lang.String; class PubCheck { public static boolean verify(String message, String signature, PublicKey publicKey) throws SignatureException{ try { Signature sign = Signature.getInstance("SHA1withRSA"); sign.initVerify(publicKey); sign.update(message.getBytes("UTF-8")); return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8"))); } catch (Exception ex) { throw new SignatureException(ex); } } public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, SignatureException { String plainData = "Hi I m here"; String pkey = "MIIBCgKCAQEA2tF2g/muNw9xKTVcIkjUMvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4eaSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HGiku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/En7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqewQwIDAQAB"; String data = "aP0nuYYA1hE5odsCkR/DcdRbBvO2Z8IOlqXf/bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP/xE7xZ8L05kjp0z2thLqO7on4C6DrG++TK1j+E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a/gdn8N2n7N/WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb+yVs3Da7E0b3/fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q=="; byte[] encodedPublicKey = pkey.getBytes( "utf-8" ); //System.out.println(new String(encodedPublicKey, "UTF-8") + "\n"); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( encodedPublicKey ); //PKCS8EncodedKeySpec publicKeySpec = new PKCS8EncodedKeySpec(encodedPublicKey); KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); PublicKey publicKey = keyFactory.generatePublic( publicKeySpec ); boolean retvar = verify(plainData, data, publicKey); // 3 - verifying content with signature and content : /*Signature sig = Signature.getInstance( "SHA256withRSA" ); sig.initVerify( publicKey ); sig.update( data.getBytes( ) ); ret = sig.verify( sign.getBytes( ) );*/ //byte[] decoded = Base64.decodeBase64(data); } } w9MSfEARtYYF6Tenfz0twaR / eI14GXmlIffflORe4eaSuMBhwQFOIKU / import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Base64; import java.security.spec.X509EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.KeyFactory; import java.security.Signature; import java.security.PublicKey; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.lang.String; class PubCheck { public static boolean verify(String message, String signature, PublicKey publicKey) throws SignatureException{ try { Signature sign = Signature.getInstance("SHA1withRSA"); sign.initVerify(publicKey); sign.update(message.getBytes("UTF-8")); return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8"))); } catch (Exception ex) { throw new SignatureException(ex); } } public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, SignatureException { String plainData = "Hi I m here"; String pkey = "MIIBCgKCAQEA2tF2g/muNw9xKTVcIkjUMvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4eaSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HGiku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/En7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqewQwIDAQAB"; String data = "aP0nuYYA1hE5odsCkR/DcdRbBvO2Z8IOlqXf/bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP/xE7xZ8L05kjp0z2thLqO7on4C6DrG++TK1j+E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a/gdn8N2n7N/WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb+yVs3Da7E0b3/fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q=="; byte[] encodedPublicKey = pkey.getBytes( "utf-8" ); //System.out.println(new String(encodedPublicKey, "UTF-8") + "\n"); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( encodedPublicKey ); //PKCS8EncodedKeySpec publicKeySpec = new PKCS8EncodedKeySpec(encodedPublicKey); KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); PublicKey publicKey = keyFactory.generatePublic( publicKeySpec ); boolean retvar = verify(plainData, data, publicKey); // 3 - verifying content with signature and content : /*Signature sig = Signature.getInstance( "SHA256withRSA" ); sig.initVerify( publicKey ); sig.update( data.getBytes( ) ); ret = sig.verify( sign.getBytes( ) );*/ //byte[] decoded = Base64.decodeBase64(data); } } + pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV + Pi1DWlxhjEhswKH88SP + gsW31gS7B / ddECUqewQwIDAQAB"; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Base64; import java.security.spec.X509EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.KeyFactory; import java.security.Signature; import java.security.PublicKey; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.lang.String; class PubCheck { public static boolean verify(String message, String signature, PublicKey publicKey) throws SignatureException{ try { Signature sign = Signature.getInstance("SHA1withRSA"); sign.initVerify(publicKey); sign.update(message.getBytes("UTF-8")); return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8"))); } catch (Exception ex) { throw new SignatureException(ex); } } public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, SignatureException { String plainData = "Hi I m here"; String pkey = "MIIBCgKCAQEA2tF2g/muNw9xKTVcIkjUMvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4eaSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HGiku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/En7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqewQwIDAQAB"; String data = "aP0nuYYA1hE5odsCkR/DcdRbBvO2Z8IOlqXf/bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP/xE7xZ8L05kjp0z2thLqO7on4C6DrG++TK1j+E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a/gdn8N2n7N/WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb+yVs3Da7E0b3/fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q=="; byte[] encodedPublicKey = pkey.getBytes( "utf-8" ); //System.out.println(new String(encodedPublicKey, "UTF-8") + "\n"); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( encodedPublicKey ); //PKCS8EncodedKeySpec publicKeySpec = new PKCS8EncodedKeySpec(encodedPublicKey); KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); PublicKey publicKey = keyFactory.generatePublic( publicKeySpec ); boolean retvar = verify(plainData, data, publicKey); // 3 - verifying content with signature and content : /*Signature sig = Signature.getInstance( "SHA256withRSA" ); sig.initVerify( publicKey ); sig.update( data.getBytes( ) ); ret = sig.verify( sign.getBytes( ) );*/ //byte[] decoded = Base64.decodeBase64(data); } } bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP / xE7xZ8L05kjp0z2thLqO7on4C6DrG ++ TK1j + E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a / gdn8N2n7N / WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb + yVs3Da7E0b3 / fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q =="; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Base64; import java.security.spec.X509EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.KeyFactory; import java.security.Signature; import java.security.PublicKey; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.lang.String; class PubCheck { public static boolean verify(String message, String signature, PublicKey publicKey) throws SignatureException{ try { Signature sign = Signature.getInstance("SHA1withRSA"); sign.initVerify(publicKey); sign.update(message.getBytes("UTF-8")); return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8"))); } catch (Exception ex) { throw new SignatureException(ex); } } public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, SignatureException { String plainData = "Hi I m here"; String pkey = "MIIBCgKCAQEA2tF2g/muNw9xKTVcIkjUMvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4eaSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HGiku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/En7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqewQwIDAQAB"; String data = "aP0nuYYA1hE5odsCkR/DcdRbBvO2Z8IOlqXf/bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP/xE7xZ8L05kjp0z2thLqO7on4C6DrG++TK1j+E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a/gdn8N2n7N/WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb+yVs3Da7E0b3/fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q=="; byte[] encodedPublicKey = pkey.getBytes( "utf-8" ); //System.out.println(new String(encodedPublicKey, "UTF-8") + "\n"); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( encodedPublicKey ); //PKCS8EncodedKeySpec publicKeySpec = new PKCS8EncodedKeySpec(encodedPublicKey); KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); PublicKey publicKey = keyFactory.generatePublic( publicKeySpec ); boolean retvar = verify(plainData, data, publicKey); // 3 - verifying content with signature and content : /*Signature sig = Signature.getInstance( "SHA256withRSA" ); sig.initVerify( publicKey ); sig.update( data.getBytes( ) ); ret = sig.verify( sign.getBytes( ) );*/ //byte[] decoded = Base64.decodeBase64(data); } } 

I compiled java code

 javac -cp commons-codec-1.10.jar:. PubCheck.java java -cp commons-codec-1.10.jar:. PubCheck 

Then the following exception is found

 Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205) at java.security.KeyFactory.generatePublic(KeyFactory.java:334) at PubCheck.main(PubCheck.java:67) Caused by: java.security.InvalidKeyException: invalid key format at sun.security.x509.X509Key.decode(X509Key.java:387) at sun.security.x509.X509Key.decode(X509Key.java:403) at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:83) at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:298) at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201) ... 2 more 

Disclaimer: I have no knowledge of Java. all the code I'm trying to find from the network.

UPDATE: the problem is finally resolved, and Java code can be checked with Maarten Bodewes. The code he provided works with one change. I need to pass PKCS1 from phpseclib. So I changed

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

to

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

PHP Code needs to be changed to use a character instead of manual encryption / hashing.

 function getKeys($keysize=2048){ $rsa = new Crypt_RSA(); $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8); $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); $d = $rsa->createKey($keysize); return array("publickey"=>$d['publickey'], "privatekey"=>$d['privatekey']); } $string = "Hi I m here"; /* $keys = getKeys(); file_put_contents("key1.pub", $keys["publickey"]); file_put_contents("key1.priv", $keys["privatekey"]); die;*/ $publickey = file_get_contents("key1.pub"); $privatekey = file_get_contents("key1.priv"); $hash = new Crypt_Hash('sha256'); $rsa = new Crypt_RSA(); $rsa->loadKey($privatekey); $rsa->setSignatureMode(CRYPT_RSA_ENCRYPTION_PKCS1); $rsa->setHash('sha256'); $signature = $rsa->sign($string); echo base64_encode($signature); 
+1
source share
2 answers

The PKCS # 1 keys almost, but not completely, match the X.509 keys.

The following snippet will create a public Java JCA key. Then it will try to decrypt (by default) OAEP.

 package nl.owlstead.stackoverflow; import static java.nio.charset.StandardCharsets.UTF_8; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.security.Signature; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; import java.util.Base64; import java.util.Base64.Decoder; import javax.crypto.Cipher; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class PKCS1PublicKey { public static RSAPublicKey fromPKCS1Encoding(byte[] pkcs1EncodedPublicKey) { // --- parse public key --- org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey; try { pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey .getInstance(pkcs1EncodedPublicKey); } catch (Exception e) { throw new IllegalArgumentException( "Could not parse BER PKCS#1 public key structure", e); } // --- convert to JCE RSAPublicKey RSAPublicKeySpec spec = new RSAPublicKeySpec( pkcs1PublicKey.getModulus(), pkcs1PublicKey.getPublicExponent()); KeyFactory rsaKeyFact; try { rsaKeyFact = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("RSA KeyFactory should be available", e); } try { return (RSAPublicKey) rsaKeyFact.generatePublic(spec); } catch (InvalidKeySpecException e) { throw new IllegalArgumentException( "Invalid RSA public key, modulus and/or exponent invalid", e); } } public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); String pkey = "MIIBCgKCAQEA2tF2g/muNw9xKTVcIkjUMvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4eaSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HGiku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/En7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqewQwIDAQAB"; Decoder decoder = Base64.getDecoder(); byte[] dpkey = decoder.decode(pkey); RSAPublicKey publicKey = fromPKCS1Encoding(dpkey); String plainData = "Hi I m here"; String data = "aP0nuYYA1hE5odsCkR/DcdRbBvO2Z8IOlqXf/bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP/xE7xZ8L05kjp0z2thLqO7on4C6DrG++TK1j+E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a/gdn8N2n7N/WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb+yVs3Da7E0b3/fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q=="; byte[] ciphertext = decoder.decode(data); // this will fail of course if the "signature" was generated using OAEP - use PSS signatures instead (see comments below) verifyBC(publicKey, plainData, ciphertext); System.out.flush(); decryptBC(publicKey, plainData, ciphertext); System.out.flush(); decryptSun(publicKey, plainData, ciphertext); System.out.flush(); } private static void decryptBC(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { Cipher oaep = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "BC"); // this *should* fail oaep.init(Cipher.DECRYPT_MODE, publicKey); byte[] plaintext = oaep.doFinal(ciphertext); System.out.println(new String(plaintext, UTF_8)); } private static void decryptSun(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { Cipher oaep = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "SunJCE"); // this fails beautifully oaep.init(Cipher.DECRYPT_MODE, publicKey); byte[] plaintext = oaep.doFinal(ciphertext); System.out.println(new String(plaintext, UTF_8)); } private static void verifyBC(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { // what should work (for PKCS#1 v1.5 signatures), requires Bouncy Castle provider Signature sig = Signature.getInstance( "SHA256withRSAandMGF1"); sig.initVerify(publicKey); sig.update(plainData.getBytes(UTF_8)); System.out.println(sig.verify(ciphertext)); } } w9MSfEARtYYF6Tenfz0twaR / eI14GXmlIffflORe4eaSuMBhwQFOIKU / package nl.owlstead.stackoverflow; import static java.nio.charset.StandardCharsets.UTF_8; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.security.Signature; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; import java.util.Base64; import java.util.Base64.Decoder; import javax.crypto.Cipher; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class PKCS1PublicKey { public static RSAPublicKey fromPKCS1Encoding(byte[] pkcs1EncodedPublicKey) { // --- parse public key --- org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey; try { pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey .getInstance(pkcs1EncodedPublicKey); } catch (Exception e) { throw new IllegalArgumentException( "Could not parse BER PKCS#1 public key structure", e); } // --- convert to JCE RSAPublicKey RSAPublicKeySpec spec = new RSAPublicKeySpec( pkcs1PublicKey.getModulus(), pkcs1PublicKey.getPublicExponent()); KeyFactory rsaKeyFact; try { rsaKeyFact = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("RSA KeyFactory should be available", e); } try { return (RSAPublicKey) rsaKeyFact.generatePublic(spec); } catch (InvalidKeySpecException e) { throw new IllegalArgumentException( "Invalid RSA public key, modulus and/or exponent invalid", e); } } public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); String pkey = "MIIBCgKCAQEA2tF2g/muNw9xKTVcIkjUMvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4eaSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HGiku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/En7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqewQwIDAQAB"; Decoder decoder = Base64.getDecoder(); byte[] dpkey = decoder.decode(pkey); RSAPublicKey publicKey = fromPKCS1Encoding(dpkey); String plainData = "Hi I m here"; String data = "aP0nuYYA1hE5odsCkR/DcdRbBvO2Z8IOlqXf/bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP/xE7xZ8L05kjp0z2thLqO7on4C6DrG++TK1j+E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a/gdn8N2n7N/WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb+yVs3Da7E0b3/fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q=="; byte[] ciphertext = decoder.decode(data); // this will fail of course if the "signature" was generated using OAEP - use PSS signatures instead (see comments below) verifyBC(publicKey, plainData, ciphertext); System.out.flush(); decryptBC(publicKey, plainData, ciphertext); System.out.flush(); decryptSun(publicKey, plainData, ciphertext); System.out.flush(); } private static void decryptBC(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { Cipher oaep = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "BC"); // this *should* fail oaep.init(Cipher.DECRYPT_MODE, publicKey); byte[] plaintext = oaep.doFinal(ciphertext); System.out.println(new String(plaintext, UTF_8)); } private static void decryptSun(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { Cipher oaep = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "SunJCE"); // this fails beautifully oaep.init(Cipher.DECRYPT_MODE, publicKey); byte[] plaintext = oaep.doFinal(ciphertext); System.out.println(new String(plaintext, UTF_8)); } private static void verifyBC(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { // what should work (for PKCS#1 v1.5 signatures), requires Bouncy Castle provider Signature sig = Signature.getInstance( "SHA256withRSAandMGF1"); sig.initVerify(publicKey); sig.update(plainData.getBytes(UTF_8)); System.out.println(sig.verify(ciphertext)); } } + pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV + Pi1DWlxhjEhswKH88SP + gsW31gS7B / ddECUqewQwIDAQAB"; package nl.owlstead.stackoverflow; import static java.nio.charset.StandardCharsets.UTF_8; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.security.Signature; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; import java.util.Base64; import java.util.Base64.Decoder; import javax.crypto.Cipher; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class PKCS1PublicKey { public static RSAPublicKey fromPKCS1Encoding(byte[] pkcs1EncodedPublicKey) { // --- parse public key --- org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey; try { pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey .getInstance(pkcs1EncodedPublicKey); } catch (Exception e) { throw new IllegalArgumentException( "Could not parse BER PKCS#1 public key structure", e); } // --- convert to JCE RSAPublicKey RSAPublicKeySpec spec = new RSAPublicKeySpec( pkcs1PublicKey.getModulus(), pkcs1PublicKey.getPublicExponent()); KeyFactory rsaKeyFact; try { rsaKeyFact = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("RSA KeyFactory should be available", e); } try { return (RSAPublicKey) rsaKeyFact.generatePublic(spec); } catch (InvalidKeySpecException e) { throw new IllegalArgumentException( "Invalid RSA public key, modulus and/or exponent invalid", e); } } public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); String pkey = "MIIBCgKCAQEA2tF2g/muNw9xKTVcIkjUMvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4eaSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HGiku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/En7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqewQwIDAQAB"; Decoder decoder = Base64.getDecoder(); byte[] dpkey = decoder.decode(pkey); RSAPublicKey publicKey = fromPKCS1Encoding(dpkey); String plainData = "Hi I m here"; String data = "aP0nuYYA1hE5odsCkR/DcdRbBvO2Z8IOlqXf/bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP/xE7xZ8L05kjp0z2thLqO7on4C6DrG++TK1j+E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a/gdn8N2n7N/WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb+yVs3Da7E0b3/fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q=="; byte[] ciphertext = decoder.decode(data); // this will fail of course if the "signature" was generated using OAEP - use PSS signatures instead (see comments below) verifyBC(publicKey, plainData, ciphertext); System.out.flush(); decryptBC(publicKey, plainData, ciphertext); System.out.flush(); decryptSun(publicKey, plainData, ciphertext); System.out.flush(); } private static void decryptBC(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { Cipher oaep = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "BC"); // this *should* fail oaep.init(Cipher.DECRYPT_MODE, publicKey); byte[] plaintext = oaep.doFinal(ciphertext); System.out.println(new String(plaintext, UTF_8)); } private static void decryptSun(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { Cipher oaep = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "SunJCE"); // this fails beautifully oaep.init(Cipher.DECRYPT_MODE, publicKey); byte[] plaintext = oaep.doFinal(ciphertext); System.out.println(new String(plaintext, UTF_8)); } private static void verifyBC(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { // what should work (for PKCS#1 v1.5 signatures), requires Bouncy Castle provider Signature sig = Signature.getInstance( "SHA256withRSAandMGF1"); sig.initVerify(publicKey); sig.update(plainData.getBytes(UTF_8)); System.out.println(sig.verify(ciphertext)); } } bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP / xE7xZ8L05kjp0z2thLqO7on4C6DrG ++ TK1j + E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a / gdn8N2n7N / WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb + yVs3Da7E0b3 / fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q =="; package nl.owlstead.stackoverflow; import static java.nio.charset.StandardCharsets.UTF_8; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.security.Signature; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; import java.util.Base64; import java.util.Base64.Decoder; import javax.crypto.Cipher; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class PKCS1PublicKey { public static RSAPublicKey fromPKCS1Encoding(byte[] pkcs1EncodedPublicKey) { // --- parse public key --- org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey; try { pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey .getInstance(pkcs1EncodedPublicKey); } catch (Exception e) { throw new IllegalArgumentException( "Could not parse BER PKCS#1 public key structure", e); } // --- convert to JCE RSAPublicKey RSAPublicKeySpec spec = new RSAPublicKeySpec( pkcs1PublicKey.getModulus(), pkcs1PublicKey.getPublicExponent()); KeyFactory rsaKeyFact; try { rsaKeyFact = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("RSA KeyFactory should be available", e); } try { return (RSAPublicKey) rsaKeyFact.generatePublic(spec); } catch (InvalidKeySpecException e) { throw new IllegalArgumentException( "Invalid RSA public key, modulus and/or exponent invalid", e); } } public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); String pkey = "MIIBCgKCAQEA2tF2g/muNw9xKTVcIkjUMvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4eaSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HGiku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/En7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtczNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqewQwIDAQAB"; Decoder decoder = Base64.getDecoder(); byte[] dpkey = decoder.decode(pkey); RSAPublicKey publicKey = fromPKCS1Encoding(dpkey); String plainData = "Hi I m here"; String data = "aP0nuYYA1hE5odsCkR/DcdRbBvO2Z8IOlqXf/bKZJiG8HELIop90Vno1dKC1qyHEAOXy0gtH7GtJamzoBjDZmHPT6eto9EZP/xE7xZ8L05kjp0z2thLqO7on4C6DrG++TK1j+E3T7V0UeU874WIB0AEVzu1XUKFW6aeuU67a/gdn8N2n7N/WXtlyNSVZXg8f4PeUhGvFJrhINZT7BuMMZj1gZs4wMJPAICwfvVeg02RPH0N3Ybf2iVgRuZlmtQXGTyBlCxe9ybdHzuQM6nXghpLNmaOzCypb+yVs3Da7E0b3/fKQ7JqPSquWex2ERZbIMSTC6oCzc1rOF6iKVAd92Q=="; byte[] ciphertext = decoder.decode(data); // this will fail of course if the "signature" was generated using OAEP - use PSS signatures instead (see comments below) verifyBC(publicKey, plainData, ciphertext); System.out.flush(); decryptBC(publicKey, plainData, ciphertext); System.out.flush(); decryptSun(publicKey, plainData, ciphertext); System.out.flush(); } private static void decryptBC(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { Cipher oaep = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "BC"); // this *should* fail oaep.init(Cipher.DECRYPT_MODE, publicKey); byte[] plaintext = oaep.doFinal(ciphertext); System.out.println(new String(plaintext, UTF_8)); } private static void decryptSun(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { Cipher oaep = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", "SunJCE"); // this fails beautifully oaep.init(Cipher.DECRYPT_MODE, publicKey); byte[] plaintext = oaep.doFinal(ciphertext); System.out.println(new String(plaintext, UTF_8)); } private static void verifyBC(RSAPublicKey publicKey, String plainData, byte[] ciphertext) throws Exception { // what should work (for PKCS#1 v1.5 signatures), requires Bouncy Castle provider Signature sig = Signature.getInstance( "SHA256withRSAandMGF1"); sig.initVerify(publicKey); sig.update(plainData.getBytes(UTF_8)); System.out.println(sig.verify(ciphertext)); } } 

OAEP SunJCE implementation will fail because it will not accept the public key for signature verification:

OAEP cannot be used to sign or verify signatures

Now this should be one of the clearest and most informative exceptions I have encountered in the cryptography API. You can also use the Bouncy Castle provider and it will "decrypt" the value of the hash function. That, however, should not use OAEP, you should use PSS to verify signatures.

Instead, you should use the PHP RSA sign , using setHash to configure SHA-256.

+3
source

Although Martin's answer works there, there is another way to get rid of an InvalidKeySpecException.

In the source code, pkey is an open-source RSA private key PKCS1. To work with the X509EncodedKeySpec (which corresponds to the X509 SubjectPublicKeyInfo certificate) there must be a PKCS8 private private key. It must also be base64 decoded.

So, in your PHP code you would not do $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1) - you would do $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS8) .

I converted your PKCS1 key to PKCS8 myself and got the following:

 String pkey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2tF2g/muNw9xKTVcIkjU" + "MvMhygtIW49yo1PgbwqDQ/w9MSfEARtYYF6Tenfz0twaR/eI14GXmlIffflORe4e" + "aSuMBhwQFOIKU/1+v1BV3RLqGGblvHTVaMVm49AGiqxNnh1LBbcSrC5UhMqlL/HG" + "iku0oYsbjLzwcLc5ac6aBQVD60wWGNm1g26lRQGRbCLqxVfcWKT3AMvEQK3cEx/E" + "n7/5Vg1V8xnJraNMrO8UGnaX8LLJFzYJiSCEShh7F+pMHbf4MaBekw7Aaf5hPJtc" + "zNsR137R92Be3OP4idI5NLmTV+Pi1DWlxhjEhswKH88SP+gsW31gS7B/ddECUqew" + "QwIDAQAB"; byte[] encodedPublicKey = Base64.decodeBase64(pkey); 

You, of course, will need to remove the existing pkey and encodedPublicKey assignments.

Alternatively, you can do return $d instead of return array("publickey"=>$d['publickey'], "privatekey"=>$d['privatekey']) in your PHP code.

+1
source

Source: https://habr.com/ru/post/1239877/


All Articles