Decrypting encrypted assertion using SAML 2.0 in java using OpenSAML - java

I have a problem while trying to decrypt encrypted assertion using SAML 2.0. The library I am using is OpenSAML Java libraries 2.5.2.
The encrypted assertion looks like this:
<EncryptedAssertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<enc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns:enc="http://www.w3.org/2001/04/xmlenc#">
<enc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
</e:EncryptionMethod>
<KeyInfo>
<o:SecurityTokenReference
xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-
1.0.xsd">
<o:KeyIdentifier
ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-
1.1#ThumbprintSHA1"
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-
message-security-1.0#Base64Binary">
1H3mV/pJAlVZAst/Dt0rqbBd67g=
</o:KeyIdentifier>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>
... ENCRYPTED KEY HERE ...
</e:CipherValue>
</e:CipherData>
</e:EncryptedKey>
</KeyInfo>
<enc:CipherData>
<enc:CipherValue>
... ENCRYPTED ASSERTIONS HERE ...
</enc:CipherValue>
</enc:CipherData>
</enc:EncryptedData>
</EncryptedAssertion>
I did convert my private key that is in PEM format to pkcs8 format using the following openssl command:
openssl pkcs8 -topk8 -nocrypt -inform PEM -in rsa_private_key.key -outform DER -out rsa_private_key.pk8
I am then ready to try to decrypt the encrypted assertion. Here is my Java code:
...
// Load the XML file and parse it.
File xmlFile = new File("data\\token.xml");
InputStream inputStream = new FileInputStream(xmlFile);
Document document = parserPoolManager.parse(inputStream);
Element metadataRoot = document.getDocumentElement();
// Unmarshall
UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(metadataRoot);
EncryptedAssertion encryptedAssertion = (EncryptedAssertion)unmarshaller.unmarshall(metadataRoot);
// Load the private key file.
File privateKeyFile = new File("data\\rsa_private_key.pk8");
FileInputStream inputStreamPrivateKey = new FileInputStream(privateKeyFile);
byte[] encodedPrivateKey = new byte[(int)privateKeyFile.length()];
inputStreamPrivateKey.read(encodedPrivateKey);
inputStreamPrivateKey.close();
// Create the private key.
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
RSAPrivateKey privateKey = (RSAPrivateKey)KeyFactory.getInstance("RSA").generatePrivate(privateKeySpec);
// Create the credentials.
BasicX509Credential decryptionCredential = new BasicX509Credential();
decryptionCredential.setPrivateKey(privateKey);
// Create a decrypter.
Decrypter decrypter = new Decrypter(null, new StaticKeyInfoCredentialResolver(decryptionCredential), new InlineEncryptedKeyResolver());
// Decrypt the assertion.
Assertion decryptedAssertion;
try
{
decryptedAssertion = decrypter.decrypt(encryptedAssertion);
}
...
Running this code always results as being unable to decrypt the assertion. I do get the following errors:
5473 [main] ERROR org.opensaml.xml.encryption.Decrypter - Error decrypting encrypted key
org.apache.xml.security.encryption.XMLEncryptionException: Key is too long for unwrapping
Original Exception was java.security.InvalidKeyException: Key is too long for unwrapping
at org.apache.xml.security.encryption.XMLCipher.decryptKey(Unknown Source)
at org.opensaml.xml.encryption.Decrypter.decryptKey(Decrypter.java:681)
at org.opensaml.xml.encryption.Decrypter.decryptKey(Decrypter.java:612)
at org.opensaml.xml.encryption.Decrypter.decryptUsingResolvedEncryptedKey(Decrypter.java:762)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:513)
at org.opensaml.xml.encryption.Decrypter.decryptDataToList(Decrypter.java:440)
at org.opensaml.xml.encryption.Decrypter.decryptData(Decrypter.java:401)
at org.opensaml.saml2.encryption.Decrypter.decryptData(Decrypter.java:141)
at org.opensaml.saml2.encryption.Decrypter.decrypt(Decrypter.java:69)
at DecrypterTool.main(DecrypterTool.java:121)
java.security.InvalidKeyException: Key is too long for unwrapping
at com.sun.crypto.provider.RSACipher.engineUnwrap(DashoA13*..)
at javax.crypto.Cipher.unwrap(DashoA13*..)
at org.apache.xml.security.encryption.XMLCipher.decryptKey(Unknown Source)
at org.opensaml.xml.encryption.Decrypter.decryptKey(Decrypter.java:681)
at org.opensaml.xml.encryption.Decrypter.decryptKey(Decrypter.java:612)
at org.opensaml.xml.encryption.Decrypter.decryptUsingResolvedEncryptedKey(Decrypter.java:762)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:513)
at org.opensaml.xml.encryption.Decrypter.decryptDataToList(Decrypter.java:440)
at org.opensaml.xml.encryption.Decrypter.decryptData(Decrypter.java:401)
at org.opensaml.saml2.encryption.Decrypter.decryptData(Decrypter.java:141)
at org.opensaml.saml2.encryption.Decrypter.decrypt(Decrypter.java:69)
at DecrypterTool.main(DecrypterTool.java:121)
5477 [main] ERROR org.opensaml.xml.encryption.Decrypter - Failed to decrypt EncryptedKey, valid decryption key could not be resolved
5477 [main] ERROR org.opensaml.xml.encryption.Decrypter - Failed to decrypt EncryptedData using either EncryptedData KeyInfoCredentialResolver or EncryptedKeyResolver + EncryptedKey KeyInfoCredentialResolver
5478 [main] ERROR org.opensaml.saml2.encryption.Decrypter - SAML Decrypter encountered an error decrypting element content
org.opensaml.xml.encryption.DecryptionException: Failed to decrypt EncryptedData
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:524)
at org.opensaml.xml.encryption.Decrypter.decryptDataToList(Decrypter.java:440)
at org.opensaml.xml.encryption.Decrypter.decryptData(Decrypter.java:401)
at org.opensaml.saml2.encryption.Decrypter.decryptData(Decrypter.java:141)
at org.opensaml.saml2.encryption.Decrypter.decrypt(Decrypter.java:69)
at DecrypterTool.main(DecrypterTool.java:121)
I really don't know what I'm doing wrong in this case. I converted my private key to pkcs8, I loaded my SAML XML data and unmarshalled it into the valid type (EncryptedAssertion) and I created a decrypted based on my private key.
Is it possible that it is related to the oaep format for RSA? I'm using the default java cryptography library.
Thanks!

For those of you who will get this problem, it was related to the fact that the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files was not installed and it was not letting me use encryption better than AES-128. Replacing the policy files with the JCE policy files, I was able to successfully decrypt my encrypted assertion.

Agree with #thwalrusnp. Just wanted to add the exact location from where you can download the policy jars.
Found it on the answer to Error while decrypting assertion sent from IDP
This happens due to limitation of cryptography strength in default
distribution of Java Runtime Environment.
Download Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files (for Java 7) (for Java 8)
Extract zip archive and find there local_policy.jar and US_export_policy.jar.
Replace your JRE version of these files under $JAVA_HOME/jre{version_number}/lib/security/ with downloaded ones.
Restart JRE process, if any running. Now you can use longer keys.

Related

Java: JWT Token Generation Using a Certificate

I am developing a backend application using Spring Boot with Java. I have to fulfill this requirement: when a specific controller of my application is called I have to return a JWT (created by me) to the client.
My application has a certificate that I created using an openssl command.
The command I used generated a .pem certificate which I converted to a .crt certificate (still using openssl).
This is the certificate (.pem version):
-----BEGIN CERTIFICATE-----
MIID3zCCAsegAwIBAgIUaQYkHJTPg5Xl29W18fl1FK3F034NFVDWòEMChvcNAQEL
BQAwfjELMAkGA1UEBhMCSVQxEDAOBgNVBAgMB0JvbG9nbmExEDAOBgNVBAcMB0Jv
bG9nbmExEjAQBgNVBAoMCVVuaXNhbHV0ZTEdMBsGA1UECwwUU3ZpbHVwcG8tTXVs
dGljYW5hbGUxGDAWBgNVBAMMD2JlLXByZW5vdGF6aW9uaTAgFw0yMTEwMTgxNjIx
MDJaGA8yMTIxMDkyNDE2MjEwMlowfjELMAkGA1UEBhMCSVQxEDAOBgNVBAgMB0Jv
bG9nbmExEDAOBgN5KLT56L5KJ6L5JK3L434NREDFEFEL3WECN4CXaqre35EdMBsG
A1UECwwUU3ZpbHVwcG8tTXVsdGljYW5hbGUxGDAWBgNVBAMMD2JlLXByZW5vdGF6
aW9uaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALrM4q5Azkjm32Ep
MvtcxnA0Ri+6m2DOOjNvJE5rn392hfiZFZcf4K/NCR8F1uM4thru3RsU5mAuhSrK
Nn58fP5KFKVJFLFJDEHWEB3R4RRIMom7PBusRXPbWM+xr0mGdP3SdXr2c71SvSBQ
KVCEBWfR86qSDSDSDSDXCXs4534rI95R7PYXSOrrH7z89u6p9unSI0OKlEwoVOhM
90JdwhVkc6TSSuFBcsFoXlUjcBDYIkZVIgXpj2+EqhDxUSKIlQr6WKWb3DYaGLyG
/9UUPAbLpMTd+D/T9d+cmM3X0WtoNSSvB30qthMFPs9Pdv5Keba7jbfYyYhpECVu
HVCujSkCAwEAAaNTMFEwHQYDVR0OBBYEFCh3SmbuLXhoCtKEq4wSqlBsPQPOMB8G
A1UdIwQYMBaAFCh3SmbuLXhoCtKEq4wSqlBsPQPOMA8GA1UdEwEB/wQFMAMBAf8w
DQYJKoZIhvcNAQELBQADggEBAA38HsRF4NPEITje0hzQmZG0Zhz2C+2EWH9Z+3ow
JfGc/y40I1WYja23zCwyUndQ5M8QXo4OYt8/yNiuGDPQf/n0QqDQ6ynwfkLkmr6m
3a7ocDT8eUFbisEZGWuYqInAi6oiRNc//NYEQOvapNkasu01p/mLhlrINoRIMwX0
JC5EovSivp05xSB6LHuT454545wddsfcwejh23jkashaksaslasLAF9348D8FlXU
X+cD5wvsGQcwmEu64BxEauDGOSybRDD6ppfSPtTivhR0UyLK9hAQB76Ns6oRbBCc
aLEzzgYhOTKHjkmI27qqUa16Jf6TFJe22Q6wbtOrEOnxDiw=
-----END CERTIFICATE-----
I need to create a JWT token (to be returned to the client) starting from this specific certificate that I have saved within my application. What is the easiest way to do this using Java (possibly with standard Java libraries)?
Unfortunately I am not an expert on tokens, public keys, private keys etc ... I just know that the JWT token I create must allow the client to authenticate to me when it calls new endpoints (managed by other controllers in my application, which will validate the token!)
I will suggest the following way to proceed further:
Follow the blog and resurrect a minimalistic running version that has JWT authentication integrated.
https://medium.com/wolox/securing-applications-with-jwt-spring-boot-da24d3d98f83
Now change AuthenticationFilter class and instead of using the hardcoded key in successfulAuthentication method use the private key of your certificate. You can retrieve the private key using bouncy castle libraries and the method defined in blog section 4.2: https://www.baeldung.com/java-read-pem-file-keys
public RSAPrivateKey readPrivateKey(File file) throws Exception {
KeyFactory factory = KeyFactory.getInstance("RSA");
try (FileReader keyReader = new FileReader(file);
PemReader pemReader = new PemReader(keyReader)) {
PemObject pemObject = pemReader.readPemObject();
byte[] content = pemObject.getContent();
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
return (RSAPrivateKey) factory.generatePrivate(privKeySpec);
}
}
Once you retrieve the RSAKey use the get the getEncoded() (https://docs.oracle.com/javase/8/docs/api/java/security/Key.html#getEncoded--)
method of retrieved RSAPRivateKey instead of KEY.getBytes() in line 54 of AuthenticationFilter class

Cannot sign a JWT using Elliptic Curve (EC) cryptography

I have generated a private key using Elliptic Curve cryptography:
openssl ecparam -genkey -name secp521r1 -noout | openssl pkcs8 -topk8 -nocrypt
I have used the following Java code to sign a JWT:
String privateKeyPEM = "MIHtAgEAMBAGByqGSM49AgEGBSuBBAAjBIHVMIHSAgEBBEEmSOGpmkjzKM+uWhya"
+ "Cl6sbSsmROUol4HaDbORnOI6klbEjbCkPEyxKRnrrtrGFShhu7TPPlGDK39f+K3G"
+ "IZhbYKGBiQOBhgAEAJQiOIKV7YmIVI30Y3y1UZIvgZFRviHFWvSiTXEG4IqzHKpF"
+ "jOIYs0rzn1F2zrFHKpmMtZ0Kh5OzyfJsGeu1GZPzANYLZQ9m13Joi3fhGFUgHLNL"
+ "0hsz/HQP89aTa9Qr8QqEP7r/vCvrcoKn9cKPGwRxOFkRgG4FWGv76F/hv+1Cj2Z7";
byte[] encoded = Base64.decodeBase64(privateKeyPEM);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
ECPrivateKey privateKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
final JwtBuilder jwtBuilder = Jwts.builder()
.setSubject("713f42c9-7df5-4271-8b53-112f30936c56")
.signWith(SignatureAlgorithm.ES512, privateKey)
.setHeaderParam("typ", "JWT");
System.out.println(jwtBuilder.compact());
However, the resulting JWT always have an invalid signature:
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJzdWIiOiI3MTNmNDJjOS03ZGY1LTQyNzEtOGI1My0xMTJmMzA5MzZjNTYifQ.MIGHAkFvCPq_BeXvATTN1duKjEf3K_Fja0ueoTuPQHC9kBc828wem7YO0vnlK6PVYXSkBk4gBaD0-OIMY_r-HS7-4-HaBwJCAMbj0k5YsBywMzme_adKTQq7YUsVvyZwGp8aVgX7vxsMhf-WNvQJSg7AG_zQiUaQ4jqtT9ZKzNoU4P5NZIGMDRCh
I can't figure out what's wrong with my code.
The posted private key is a PKCS#8 key. From this the following public X.509 key can be derived:
-----BEGIN PUBLIC KEY-----
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAlCI4gpXtiYhUjfRjfLVRki+BkVG+
IcVa9KJNcQbgirMcqkWM4hizSvOfUXbOsUcqmYy1nQqHk7PJ8mwZ67UZk/MA1gtl
D2bXcmiLd+EYVSAcs0vSGzP8dA/z1pNr1CvxCoQ/uv+8K+tygqf1wo8bBHE4WRGA
bgVYa/voX+G/7UKPZns=
-----END PUBLIC KEY-----
If a JWT is created with the posted code, e.g.:
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJzdWIiOiI3MTNmNDJjOS03ZGY1LTQyNzEtOGI1My0xMTJmMzA5MzZjNTYifQ.AE0sx6wHk2xBPkbam24n8NE39qkB0YX4j65DhrWyBKtaQXRMZjuzV78vFir3scfXVolFOf2gpo2K6x_hu0jPz-0IAIMbYQsglePQHQ9OZMSb2XAxKCVXccdvW27QeBov-VGUxxlL-CFNviaPaAGbNny_sc8cRjIF97pDD4KjOPBKkZzt
then this can be verified without problems with this public key, check it e.g. here, i.e. the posted code produces a valid signature.
On the other hand, the JWT posted in the question:
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJzdWIiOiI3MTNmNDJjOS03ZGY1LTQyNzEtOGI1My0xMTJmMzA5MzZjNTYifQ.MIGHAkFvCPq_BeXvATTN1duKjEf3K_Fja0ueoTuPQHC9kBc828wem7YO0vnlK6PVYXSkBk4gBaD0-OIMY_r-HS7-4-HaBwJCAMbj0k5YsBywMzme_adKTQq7YUsVvyZwGp8aVgX7vxsMhf-WNvQJSg7AG_zQiUaQ4jqtT9ZKzNoU4P5NZIGMDRCh
can indeed not be verified. The signature of this JWT is Base64url decoded:
30818702416f08fabf05e5ef0134cdd5db8a8c47f72bf1636b4b9ea13b8f4070bd90173cdbcc1e9bb60ed2f9e52ba3d56174a4064e2005a0f4f8e20c63fafe1d2efee3e1da07024200c6e3d24e58b01cb033399efda74a4d0abb614b15bf26701a9f1a5605fbbf1b0c85ff9636f4094a0ec01bfcd0894690e23aad4fd64accda14e0fe4d64818c0d10a1
and thus ASN.1 encoded, s. here and here. However, JWTs use a signature encoded as r|s, see e.g. here. If the signature is converted to this encoding, the result is:
6f08fabf05e5ef0134cdd5db8a8c47f72bf1636b4b9ea13b8f4070bd90173cdbcc1e9bb60ed2f9e52ba3d56174a4064e2005a0f4f8e20c63fafe1d2efee3e1da07c6e3d24e58b01cb033399efda74a4d0abb614b15bf26701a9f1a5605fbbf1b0c85ff9636f4094a0ec01bfcd0894690e23aad4fd64accda14e0fe4d64818c0d10a1
If this is Base64url encoded and used in the posted JWT (instead of the old signature), that is:
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJzdWIiOiI3MTNmNDJjOS03ZGY1LTQyNzEtOGI1My0xMTJmMzA5MzZjNTYifQ.bwj6vwXl7wE0zdXbioxH9yvxY2tLnqE7j0BwvZAXPNvMHpu2DtL55Suj1WF0pAZOIAWg9PjiDGP6_h0u_uPh2gfG49JOWLAcsDM5nv2nSk0Ku2FLFb8mcBqfGlYF-78bDIX_ljb0CUoOwBv80IlGkOI6rU_WSszaFOD-TWSBjA0QoQ
the JWT can be successfully validated.
Since the posted code generates an RFC compliant JWT (with r|s signature), the JWT posted in the question was probably not generated with the posted code (because of the ASN.1 signature).
Update: According to the jjwt bugtracker there is a bug (#125) that causes the signature to be signed incorrectly with ASN.1. This bug should be fixed with jjwt 0.7 and would be a plausible explanation for your issue, provided you are working with an affected version (the bug is from 05.2016).I have tested your code with jjwt 0.9.1 (from 07.2018), which generates a valid signature, meaning it works.The current version is jjwt 0.11.2 (from 06.2020), which also works according to the other answer.So if you are working with an affected version, it would be best to use a newer / the current jjwt version. If this is not possible for some reason you can of course convert the signature manually from ASN.1 to r|s encoding.
My IntelliJ is claiming that the "signWith"-line is deprecated.
So changing your code
final JwtBuilder jwtBuilder = Jwts.builder()
.setSubject("713f42c9-7df5-4271-8b53-112f30936c56")
.signWith(SignatureAlgorithm.ES512, privateKey)
.setHeaderParam("typ", "JWT");
to
final JwtBuilder jwtBuilder = Jwts.builder()
.setSubject("713f42c9-7df5-4271-8b53-112f30936c56")
.signWith(privateKey, SignatureAlgorithm.ES512)
.setHeaderParam("typ", "JWT");
is giving this JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJzdWIiOiI3MTNmNDJjOS03ZGY1LTQyNzEtOGI1My0xMTJmMzA5MzZjNTYifQ.ALFk_BGerAstughF4ssl5eGQmx0mu5jvWb13QB228hAD5g8dwM-NvBsyevCuYUXLBJKzIUdPL-LVwQoPkwIbYrKhACzKwUwRN_v3IX2GIPW2ctTcRGPwA7gUaDWrOtwqcHALSfk20QZXT2TQfOnXX8tv0vhXLK_SnnHH5o1b96sa_HSR
As you only provided the ec private key I used OpenSSL to generate the EC Public key and passed the JWT and public key to the Online JWT verifier https://jwt.io/
and got the result "Signature verified".

Key bytes cannot be specified for RSA signatures. Please specify a PublicKey or PrivateKey instance

I'm trying to decode a JWT token from my OAUTH server and I'm using examples from the following website.
I have tried quite a lot self designed solutions but can't solve an issue, I can't decode a RSA public key signed JWT.
The following code
Jwts.parser().setSigningKey("<<Oauth server RSA public key>>").parseClaimsJws(keySec.getTokenString());
I get the following Exception
java.lang.IllegalArgumentException: Key bytes cannot be specified for RSA signatures. Please specify a PublicKey or PrivateKey instance.

DER Encode BCECPublicKey

I'm trying to Der encode a public key, and use it with an external service.
When I get the encoded org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey and send it to the external service, it responds with "ECDSA certificates with unnamed curves are unsupported". (I'm calling publicKey.getEncoding() to get the encoded key)
publicKey.getFormat();
// "X.509"
publicKey.getAlgorithm();
// "ECDH"
publicKey.getQ().curve.getClass().name;
// "org.bouncycastle.math.ec.custom.sec.SecP256R1Curve"
I'm not really sure how to debug from here. I tried saving the raw encoded bytes
to a file and inspecting the cert with openssl without success:
> openssl x509 -in test.der -inform der -text -noout
unable to load certificate
62375:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.30.2/src/crypto/asn1/tasn_dec.c:1344:
62375:error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.30.2/src/crypto/asn1/tasn_dec.c:848:
62375:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.30.2/src/crypto/asn1/tasn_dec.c:768:Field=serialNumber, Type=X509_CINF
62375:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.30.2/src/crypto/asn1/tasn_dec.c:768:Field=cert_info, Type=X509
Any help would be greatly appreciated!
Here's the solution I came up with:
KeyFactory keyFactory = KeyFactory.getInstance("EC");
X509EncodedKeySpec keySpec = keyFactory.getKeySpec(publicKey, X509EncodedKeySpec.class);
return keySpec.getEncoded();

RSA public key generation issue (PHP/Java integration)

I have one server and one client.
Client might be in different technologies like java , php.
server code is written in java.
What I am doing in server is, get exponent and modulus bytes of client public key and generate public key of client.
To generate client public key I am using the code below:
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulusBigInt,exponentBigInt);
keyFactory = KeyFactory.getInstance("RSA", "BC");
RSAPublicKey clientPublicKey = (RSAPublicKey) keyFactory.generatePublic(spec);
To encrypt data using client public key I am using below code:
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, clientPublickey);
scrambled = cipher.doFinal(buffer);
Server Information
I have implemented RSA-1024 to encrypt AES key.
I am using RSA/ECB/PKCS1Padding algorithm. and I have also make sure that all clients have also consider 1 padding in their code.
Client - 1 (Java)
If client is also made in java than public key is successfully generated from exponent and modulus of client public key.
I am using the code below to generate key pair of client RSA key..
keyPairGene = KeyPairGenerator.getInstance("RSA");
keyPairGene.initialize(1024);
KeyPair keyPair = keyPairGene.genKeyPair();
RSAPublicKey clientPublickey = (RSAPublicKey) keyPair.getPublic();
Client -2 (php)
Now the problem is if client is in php .. than public key is successfully generated but when I try to encrypt using that public key at that time bad padding exception occurs when I have used default provider in server.
I am using bellow code to generate key pair of client RSA key..
$options = array('private_key_bits' => 1024,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
'config' => realpath(__DIR__) . '/openssl.cnf');
#Generates New Private / Public Key Pair
$pkGenerate = openssl_pkey_new($options);
#Get Client Private Key
openssl_pkey_export($pkGenerate, $PrivateKey, NULL, $options);
#Get Client Public Key
$keyData = openssl_pkey_get_details($pkGenerate);
Than I have tried BC provider ... It gives me the exception below:
org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.
I am not getting what is the problem occurs when I am trying to generate public key from exponent and modulus when client is in php...
if client is in java than its no issues.... and works perfectly..
Any type of help is welcome...
Note:
What I have observed from debugging code is ,
client's public key modulus byte's bit length at server side is varies between 1020 to 1023... it never reaches at 1024 though we have define size as 1024.
Still don't get what exactly the problem is...
but I have implemented work around for it...
I got stuck in generating public key of client using exponent and modulus.
So now I have used one standard format of public key certificate - DER & PEM.
What I did is, generated DER or PEM from PHP side using bellow code,
$options = array('private_key_bits' => 1024,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
'config' => realpath(__DIR__) . '/openssl.cnf');
#Get Client Public Key
$keyData = openssl_pkey_get_details($pkGenerate);
$clientPublicKey = $keyData['key'];
$this->clientData['clientPublicKeyPEM'] = $keyData['key'];
And then send that generated PEM to Server (Java).
And at server side I have developed bellow code to regenerate Public key from POM string.
KeyFactory keyFactory=KeyFactory.getInstance("RSA");
byte[] pubKeyBits = Base64.decodeBase64(clientPublickeyView.getModulusBytes());
PublicKey pubKey=keyFactory.generatePublic(new X509EncodedKeySpec(pubKeyBits));

Categories