How to decrypt data using private key(.private) in java - java

Data is encrypted using OpenSSL in PHP and i would like to decrypt java but getting error in java
Code for Encryption in PHP-
public function getEncryptedString($cardNumber,$key_id){
$encryptedCardNumber = '';
$key_name = "key_{$key_id}";
$pub_key_path =$key_name.".public";
$fp=fopen ($pub_key_path,"r"); //Open the public key (key_8.public)
$pub_key = fread($fp,8192); //Read public key key (key_8.public) into
fclose($fp);
openssl_public_encrypt($cardNumber,$encryptedCardNumber,$pub_key);
if($key_id > 4) return rawurlencode(base64_encode($encryptedCardNumber));
else return addslashes($encryptedCardNumber);
}
Code for Decryption in JAVA-
public static String getDecryptedValue(int keyId,String encryptedCCNumber ,String passPhrase){
String result="";
String privateKeyFileName="key_8.private";
String privateKeyLocation= PropertiesUtil.getProperty("PUBLIC_PRIVATE_KEY_LOCATION");
String privateKeyFileNameLocation=privateKeyLocation+privateKeyFileName;
String decryptedValue= getDecryptedMessage(privateKeyFileNameLocation,encryptedCCNumber,passPhrase);
return result;
}
public static String getDecryptedMessage(String privateKeyFileNameLocation, String encryptedCCNumber,String passPhrase)
{
byte[] decodedBytesCCNumber= Base64.decodeBase64(encryptedCCNumber.getBytes());
byte[] decryptedMessage=null;
try {
Cipher cipher = Cipher.getInstance("RSA");
PrivateKey privateKey = getPrivateKey(privateKeyFileNameLocation,passPhrase);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
decryptedMessage = cipher.doFinal(decodedBytesCCNumber);
} catch (Throwable t) {
t.printStackTrace();
}
System.out.println("new String(decryptedMessage)"+new String(decryptedMessage));
return new String(decryptedMessage);
}
private static PrivateKey getPrivateKey(String privateKeyFileNameLocation,String passPhrase) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream(privateKeyFileNameLocation), passPhrase.toCharArray());
String alias = (String) ks.aliases().nextElement();
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(passPhrase.toCharArray()));
return keyEntry.getPrivateKey();
}
Java code is giving below error.
java.io.IOException: toDerInputStream rejects tag type 45
at sun.security.util.DerValue.toDerInputStream(DerValue.java:847)
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1221)
at java.security.KeyStore.load(KeyStore.java:1214)

You are URL-encoding a Base64-encoding of the ciphertext, but you are only deciphering a base64-decoding of it. Either lose the URL-encoding or decode it at the receiver.

Related

Not able to verify digital signature in Pdf file

I have a digitally signed pdf file and I am trying to verify the signature in that. But Signature is not getting verified. Below is the code
public static void main(String[] args) throws Exception {
HashMap<String, Object> keyPair = new HashMap<>();
String password = "123";
KeyStore keyStore = KeyStore.getInstance("pkcs12"); //, "BC");
keyStore.load(new FileInputStream("/Users/shivam/Documents/Projects/label-processor/src/main/resources/DigitalSignatureFile.pfx"), password.toCharArray());
Enumeration<String> keyStoreAliasEnum = keyStore.aliases();
String alias = null;
PublicKey publicKey = null;
PrivateKey privateKey = null;
byte[] signature = null;
while ( keyStoreAliasEnum.hasMoreElements() ) {
alias = keyStoreAliasEnum.nextElement();
if (password != null) {
privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
X509Certificate x509Certificate = (X509Certificate) keyStore.getCertificate(alias);
publicKey = x509Certificate.getPublicKey();
signature = x509Certificate.getSignature();
keyPair.put("Alias", alias);
keyPair.put("PublicKey", publicKey);
keyPair.put("PrivateKey", privateKey);
keyPair.put("X509Certificate", x509Certificate);
}
}
verify(publicKey, signature);
}
public static void verify(PublicKey publicKey, byte[] sigBytes) throws Exception {
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify(publicKey);
FileInputStream datafis = new FileInputStream("/Users/shivam/Desktop/DigitallySignedFile.pdf");
byte[] data = IOUtils.toByteArray(datafis);
sig.update(data);
boolean verifies = sig.verify(sigBytes);
System.out.println("signature verifies: " + verifies);
FileUtils.writeByteArrayToFile(
new File("/Users/shivam/Documents/Projects/label-processor/src/main/resources/VerifiedFile.pdf"),
data
);
}
Above program is giving "Signature verifies: false". And In VerifiedFile.pdf I am still seeing signature not verified. But when I am trying to verify in Adobe Reader it is verifying correctly.
I tried verifying with the help of itext library also. It is verifying signature But In pdf it still shows signature not verified.
public static void main(String[] args) throws Exception {
byte[] pdfBytes = Files.readAllBytes(
Paths.get("/Users/shivam/Desktop/DigitallySignedFile.pdf")
);
PdfReader pdfReader = new PdfReader(pdfBytes);
AcroFields acroFields = pdfReader.getAcroFields();
List<String> signatures = acroFields.getSignatureNames();
boolean valid = false;
if (!signatures.isEmpty()) {
for (String signature : signatures) {
if (acroFields.signatureCoversWholeDocument(signature)) {
PdfPKCS7 pkcs7 = acroFields.verifySignature(signature);
valid = pkcs7.verify();
String reason = pkcs7.getReason();
Calendar signedAt = pkcs7.getSignDate();
X509Certificate x509Certificate = pkcs7.getSigningCertificate();
Principal issuerDN = x509Certificate.getIssuerDN();
Principal subjectDN = x509Certificate.getSubjectDN();
logger.info("valid = {}, date = {}, reason = '{}', issuer = '{}', subject = '{}'",
valid, signedAt.getTime(), reason, issuerDN, subjectDN);
break;
}
}
}
FileUtils.writeByteArrayToFile(
new File("/Users/shivam/Documents/Projects/label-processor/src/main/resources/VerifiedFile.pdf"),
pdfBytes
);
}
I appreciate any help.

Porting python PKCS1_v1_5 encryption code to java generating different signatures

I am trying to port my working python code for generating signature to java but they both are producing different signatures. Here is my code for python which is generating the signature.
import pdb
pdb.set_trace()
signer = PKCS1_v1_5.new(priv_key)
digest = SHA256.new()
digest.update(message)
val = signer.sign(digest)
return val
I am calling this function using this statement
signature = b64encode(sign(msg1, private))
Here the msg1 is
msg1 = 'test'.encode("utf8")
and private is the private key which I am importing using
RSA.importKey("<Location of key>"
I am trying to write a similar java code for implementing the same functionality with this given code
public static void main(String[] args) throws Exception {
String payload = "test";
String dig = makeDigest( payload, "SHA-256");
Key k = getPrivateKey("private_key.der");
String signature = encrypt(dig, "RSA", k);
System.out.print(signature);
}
public static String makeDigest(String payload, String digestAlgo) {
String strDigest = "";
try {
MessageDigest md = MessageDigest.getInstance(digestAlgo);
byte[] p_b = payload.getBytes("UTF-8");
md.update(p_b);
byte[] digest = md.digest();
char[] encoded = Hex.encodeHex(digest);
strDigest = new String(encoded);
System.out.println(strDigest);
}
catch (Exception ex) {
ex.printStackTrace();
}
return strDigest;
}
public static String encrypt(String sha, String encryptAlgo, Key k) {
String strEncrypted = "";
try {
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(encryptAlgo,"BC");
cipher.init(Cipher.ENCRYPT_MODE, k);
byte[] encrypted = cipher.doFinal(sha.getBytes("UTF-8"));
//System.out.println(new String(encrypted));
byte[] encoded = Base64.getEncoder().encode(encrypted);
strEncrypted = new String(encoded);
}
catch (Exception ex) {
ex.printStackTrace();
}
return strEncrypted;
}
public static PrivateKey getPrivateKey(String filename)
throws Exception {
byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
Security.addProvider(new BouncyCastleProvider());
KeyFactory kf = KeyFactory.getInstance("RSA","BC");
return kf.generatePrivate(spec);
}
Both thee codes are generating different signatures. I feel something I am doing wrong in selecting the algorithm on Java side. I have tried with
RSA/NONE/PKCS1Padding
and
RSA/ECB/PKCS1Padding
but still, it is different signature as compared to python code.
Any lead on this will be very helpful.

Bouncy Castle PQC XMSS signing: NullPointerException after retrieving SecretKey from KeyStore

While rebuilding JarSigner in order to work with PQC Signature Schemes such as XMSS provided by the JCA/JCE Provider BouncyCastle I came across a problem: It seems that XMSS PrivateKeys cannot be used to sign stuff anymore after being stored and retrieved from disk. However XMSSMT and SPHINCS PrivateKeys can. Why ?
The Source Code for you to test it yourself is at the bottom.
You will need 2 external libraries for it to work:
the Bouncy Castle Provider
a Bouncy Castle utility library to generate X.509 Certificates
N.B.: The Source Code is about saving and retrieving the Key in/from a KeyStore. But I also tried saving it simply to a file which does not work either.
The Error I get:
java.security.SignatureException: java.lang.NullPointerException
at org.bouncycastle.pqc.jcajce.provider.xmss.XMSSSignatureSpi.engineSign(Unknown Source)
at java.base/java.security.Signature.sign(Signature.java:598)
at Main.sign(Main.java:91)
at Main.run(Main.java:71)
at Main.main(Main.java:22)
[Main]
public class Main {
public static String keyStorePath = "myKeyStore.keystore";
public static void main(String[] args) throws InterruptedException {
String[] algs = {"XMSS", "XMSS", "XMSSMT", "XMSSMT", "SPHINCS256"},
digests = {"SHA256", "SHA512", "SHA256", "SHA512", "SHA512"};
for (int i = 0; i < algs.length; i++){
try {
run(algs[i], digests[i]);
}catch (Exception ignore){
ignore.printStackTrace();
Thread.sleep(60); // Wait for print
}
}
}
public static void run(String alg, String digest) throws Exception{
String sigAlg = digest + "with" + alg,
provider = "BCPQC",
keyStoreProvider = "BC",
keyStoreAlias = sigAlg, // for readability
keyStorePassword = "password";
System.out.println("Running " + sigAlg + ".");
// Add providers
addProvider(new String[] {provider, keyStoreProvider});
// Generate KeyPairs
KeyPairGenerator kpg = KeyPairGenerator.getInstance(alg, provider);
initialize(kpg, alg, digest);
KeyPair myKp = kpg.generateKeyPair();
// Sign
sign(myKp.getPrivate(), sigAlg, provider, "Hello World!");
// Generate a self-signed certificate
X509Certificate cert = BCCertGen.generate(myKp.getPrivate(), myKp.getPublic(), 365, sigAlg, true);
// Load a KeyStore
KeyStore keyStore = KeyStore.getInstance("PKCS12", keyStoreProvider);
try {
keyStore.load(new FileInputStream(keyStorePath), keyStorePassword.toCharArray());
}catch (Exception ingore){
// If there is no KeyStore at #keyStorePath
// create an empty one
keyStore.load(null, keyStorePassword.toCharArray());
}
// Store the generated KeyPair with the Certificate in the KeyStore
keyStore.setKeyEntry(keyStoreAlias, myKp.getPrivate(), keyStorePassword.toCharArray(), new X509Certificate[] {cert});
keyStore.store(new FileOutputStream(keyStorePath), keyStorePassword.toCharArray());
// Load the stored PrivateKey from the KeyStore
keyStore.load(new FileInputStream(keyStorePath), keyStorePassword.toCharArray());
PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyStoreAlias, keyStorePassword.toCharArray());
// Sign again
sign(privateKey, sigAlg, provider, "Hello World!");
}
public static void addProvider(String[] providers){
for (String provider : providers) {
switch (provider) {
case "BCPQC":
Security.addProvider(new BouncyCastlePQCProvider());
break;
case "BC":
Security.addProvider(new BouncyCastleProvider());
break;
}
}
}
public static void sign(PrivateKey pk, String sigAlg, String provider , String payload) throws Exception{
Signature signer = Signature.getInstance(sigAlg, provider);
signer.initSign(pk);
signer.update(payload.getBytes());
signer.sign();
System.out.println("Successfully signed");
}
public static void initialize(KeyPairGenerator kpg, String alg, String digest) throws Exception {
switch (alg) {
case "XMSS":
kpg.initialize(new XMSSParameterSpec(4, digest));
break;
case "XMSSMT":
kpg.initialize(new XMSSMTParameterSpec(4, 2, digest));
break;
case "SPHINCS256":
kpg.initialize(new SPHINCS256KeyGenParameterSpec());
break;
case "RSA":
kpg.initialize(new RSAKeyGenParameterSpec(2048, new BigInteger("5")));
break;
}
}
}
[BCCertGen]
public class BCCertGen {
public static String _country = "Westeros",
_organisation = "Targaryen",
_location = "Valyria",
_state = "Essos",
_issuer = "Some Trusted CA";
public BCCertGen(String country, String organisation, String location, String state, String issuer){
_country = country;
_organisation = organisation;
_location = location;
_state = state;
_issuer = issuer;
}
public static X509Certificate generate(PrivateKey privKey, PublicKey pubKey, int duration, String signAlg, boolean isSelfSigned) throws Exception{
Provider BC = new BouncyCastleProvider();
// distinguished name table.
X500NameBuilder builder = createStdBuilder();
// create the certificate
ContentSigner sigGen = new JcaContentSignerBuilder(signAlg).build(privKey);
X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
new X500Name("cn="+_issuer), //Issuer
BigInteger.valueOf(1), //Serial
new Date(System.currentTimeMillis() - 50000), //Valid from
new Date((long)(System.currentTimeMillis() + duration*8.65*Math.pow(10,7))), //Valid to
builder.build(), //Subject
pubKey //Publickey to be associated with the certificate
);
X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen));
cert.checkValidity(new Date());
if (isSelfSigned) {
// check verifies in general
cert.verify(pubKey);
// check verifies with contained key
cert.verify(cert.getPublicKey());
}
ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded());
CertificateFactory fact = CertificateFactory.getInstance("X.509", BC);
return (X509Certificate) fact.generateCertificate(bIn);
}
private static X500NameBuilder createStdBuilder() {
X500NameBuilder builder = new X500NameBuilder(RFC4519Style.INSTANCE);
builder.addRDN(RFC4519Style.c, _country);
builder.addRDN(RFC4519Style.o, _organisation);
builder.addRDN(RFC4519Style.l, _location);
builder.addRDN(RFC4519Style.st, _state);
return builder;
}
}
This is a known issue: https://github.com/bcgit/bc-java/issues/380
Just use a beta version higher than 161b01 as suggested.

3DES and RSA encryption of values for Web Service work in C# but not in Java

I have a requirement in which I have to communicate with a
Web Service by sending three parameters that are encrypted: ID, key and initialization vector (IV). In order to do this, I need to use Triple DES (3DES/DESede) encryption as well as RSA encryption. The steps required to do this are:
Start with the ID in clear text. Decode the ID from a base64 string to an array of bytes. The original ID is not base64 encoded but this step must be performed.
Encrypt the base64 decoded ID using 3DES and generate the key and IV
Encrypt the key and IV generated with RSA (using a certificate provided)
Convert encrypted ID, encrypted key and IV to base64 strings.
I was provided with a C# example on how to do this and the code looks as displayed below:
namespace SampleEncryption
{
public class SampleWebServiceInvocation
{
private const string CERT_SUBJECT = "sample.cer";
public string GetReport()
{
ReportService.RService ws = new ReportService.RService();
ReportService.ReportRequest req = new ReportService.ReportRequest();
string key = string.Empty;
string iv = string.Empty;
string id = "1234567890123456";
string encrypt = new CryptEx().EncryptEx(id, CERT_SUBJECT, ref key, ref iv);
req.AccountNumber = encrypt;
req.Key = key;
req.InitializationVector = iv;
ReportService.ReportResponse resp = ws.getReport(req);
if (resp.Success)
return resp.RedirectUrl;
return string.Empty;
}
}
/// <summary>
/// CryptorEx
/// </summary>
public class CryptEx
{
private X509Certificate2 _certificate;
private byte[] _encryptedKey;
private byte[] _encryptedIV;
private byte[] _encryptedText;
private byte[] _decryptedKey;
private byte[] _decryptedIV;
private byte[] _decryptedText;
/// <summary>
/// Default (empty) constructor
/// </summary>
public CryptEx()
{
}
/// <summary>
/// Publicly exposed encrypt method
/// </summary>
public string EncryptEx(string decryptedText, string certSubject, ref string key, ref string iv)
{
string data;
_decryptedText = Convert.FromBase64String(decryptedText);
try
{
_certificate = GetSignerCert(certSubject);
_encryptedText = EncryptWithTripleDES();
EncryptWithRSA();
key = Convert.ToBase64String(_encryptedKey);
iv = Convert.ToBase64String(_encryptedIV);
data = Convert.ToBase64String(_encryptedText);
}
catch (Exception)
{
data = string.Empty;
}
return data;
}
private byte[] EncryptWithTripleDES()
{
//Create a crypto provider for the text
using (TripleDESCryptoServiceProvider tripDes = new TripleDESCryptoServiceProvider())
{
tripDes.Mode = CipherMode.CBC;
ICryptoTransform encryptor = tripDes.CreateEncryptor();
//Encrypt
using (MemoryStream ms = new MemoryStream())
{
CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
cs.Write(_decryptedText, 0, _decryptedText.Length);
cs.FlushFinalBlock();
cs.Close();
ms.Close();
_decryptedKey = tripDes.Key;
_decryptedIV = tripDes.IV;
return ms.ToArray();
}
}
}
private void EncryptWithRSA()
{
using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)_certificate.PublicKey.Key)
{
_encryptedKey = rsa.Encrypt(_decryptedKey, false);
_encryptedIV = rsa.Encrypt(_decryptedIV, false);
}
}
private static X509Certificate2 GetSignerCert(string certName)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
try
{
store.Open(OpenFlags.ReadOnly);
// First, find certificates that haven't expired
X509Certificate2Collection validCerts = store.Certificates.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scorecardCerts = validCerts.Find(X509FindType.FindBySubjectName, certName, false);
if (scorecardCerts.Count == 0)
throw new ApplicationException(string.Format("Unable to find certificate with name of {0}", certName));
if (scorecardCerts.Count > 1)
throw new ApplicationException(string.Format("More than one certificate has a name of {0}\r\n{1}",
certName, GetSubjectNames(scorecardCerts)));
return scorecardCerts[0];
}
finally
{
store.Close();
}
}
private static string GetSubjectNames(X509Certificate2Collection signingCert)
{
StringBuilder sb = new StringBuilder();
foreach (X509Certificate2 cert in signingCert)
sb.AppendLine(cert.Subject);
return sb.ToString();
}
}
}
In my case, I need to do this but in Java, so here I expose the logic of my implementation.
For Triple DES:
public class DESedeCrypto implements SymmetricCryptoManager {
/**
* Constant for the algorithm being used for Triple DES (CBC)
*/
public static final String DESEDE_CBC_TRANSFORMATION_ALG = "DESede/CBC/NoPadding";
#Override
public DESedeEncryptionResult encrypt(byte[] srcData, String cryptoAlgorithm) throws Exception {
DESedeEncryptionResult result = null;
byte[] encryptedBytes = null;
byte[] initializationVector = null;
if (srcData == null || srcData.length == 0) {
throw new InvalidEncryptionTargetException();
}
KeyGenerator keyGen = KeyGenerator.getInstance("DESede");
SecretKey secretKey = keyGen.generateKey();
Cipher cipher = Cipher.getInstance(cryptoAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
result = new DESedeEncryptionResult();
if (cryptoAlgorithm.equals(DESEDE_CBC_TRANSFORMATION_ALG)) {
IvParameterSpec spec = cipher.getParameters().getParameterSpec(IvParameterSpec.class);
initializationVector = spec.getIV();
result.setInitializationVector(initializationVector);
}
encryptedBytes = cipher.doFinal(srcData);
result.setResultBytes(encryptedBytes);
result.setKeyBytes(secretKey.getEncoded());
return result;
}
}
For RSA:
public class RSACrypto implements AsymmetricCryptoManager {
/**
* Tranformation algorithm for OAEP.
*/
private static final String OAEP_RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";
/**
* Constructor of the class.
*/
public RSACrypto() {
}
#Override
public byte[] encryptWithCertificate(InputStream inputStream, byte[] targetBytes) throws Exception {
byte[] encryptedBytes = null;
if (targetBytes == null || targetBytes.length == 0) {
throw new InvalidEncryptionTargetException();
}
if (inputStream == null) {
throw new InvalidCertificatePathException("Resource specified for operation is not valid");
}
X509Certificate certificate = CryptoUtils.readCertificateFromInputStream(inputStream);
encryptedBytes = getEncryptedBytes(certificate, targetBytes);
return encryptedBytes;
}
private byte[] getEncryptedBytes(X509Certificate certificate, byte[] targetBytes) throws Exception {
byte[] encryptedBytes = null;
PublicKey publicKey = certificate.getPublicKey();
Cipher cipher = Cipher.getInstance(OAEP_RSA_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
encryptedBytes = cipher.doFinal(targetBytes);
return encryptedBytes;
}
}
Here's how I read the certificate:
public static X509Certificate readCertificateFromInputStream(InputStream inputStream) throws Exception {
X509Certificate certificate = null;
CertificateFactory certFactory = CertificateFactory.getInstance(X509_CERT_TYPE);
certificate = (X509Certificate) certFactory.generateCertificate(inputStream);
return certificate;
}
And here is the logic of the whole encryption process:
String base64id = new String(CryptoUtils.encodeBase64(base64id.getBytes()));
DESedeEncryptionResult encryptionResult = desedeCrypto.encrypt(CryptoUtils.decodeBase64(base64id), DESedeCrypto.DESEDE_CBC_TRANSFORMATION_ALG);
byte[] rsaEncryptedKey = rsaCrypto.encryptWithCertificate(certForKeyInputStream, encryptionResult.getKeyBytes());
byte[] rsaEncryptedIv = rsaCrypto.encryptWithCertificate(certForIvInputStream, encryptionResult.getInitializationVector());
String encryptedId = CryptoUtils.getBase64EncodedStr(encryptionResult.getResultBytes());
String finalEncryptedKey = CryptoUtils.getBase64EncodedStr(rsaEncryptedKey);
String finalIv = CryptoUtils.getBase64EncodedStr(rsaEncryptedIv);
The ID used for testing is: 1234567890123456
When I send the results to the Web Service I receive a message that the encryption cannot be done. In order to make sure, I tested both implementations (Java and c#). C# generated values are working when I send them to the web service, but Java implementation is not working.
Do you know if there's some specific type of algorithm I'd need to add to the Java implementation, I mean in Triple DES we use DESede/CBC/NoPadding but maybe c# uses another. Same for RSA.
Maybe somebody can give a me clue or recommendation regarding this? Thanks in advance.

Exception when initializing PublicKey from RSA public key stored as a string (works on laptop, not on server)

I have a application I am working on that deals with handling certificates and I am running into a issue where my code works correct when I run in via JUnit tests locally on my laptop but when I actually deploy the code to my server I am getting a exception. The exception is happening while creating a PublicKey from a RSA public key stored in a String. I am hoping someone might be able to point me in a direction to look why it fails on the server but works in the Junit.
My RSA Public Key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvNEz3+TStAAndHTc1qwT
NGvZYyB7DD1FshQf+mbQUGJ9HccOXNn5oHB7fWQjODjlDrYyCs7FclSMTLxA3lHX
98QWeWHL2O8t8qrJQQEUWZITmr/ddiNJOOvMeYF0K5if4m84vjgx/pTwwAVyU0Yo
MMXPnRozO8o7zSyRsH4jixALDugrsveEjLQI/cIEFvNjqlhyfumHyJKywNkMH1oJ
4e/f89FkpeDV694lsLs1jguuLLnvroXYJ5Uzeos+F0Pj1zFDUvhWrjVwxsUfAxS8
5uFGTUm6EEl9XiKwi+mgg8ODrY5dh3uE2yKB2T1Qj8BfK55zB8cYbORSsm6/f6Bi
BwIDAQAB
-----END PUBLIC KEY-----
My Junit Code: <- Works from laptop
#Test
public void testkey() throws Exception {
String pem = "-----BEGIN PUBLIC KEY-----"+
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvNEz3+TStAAndHTc1qwT"+
"NGvZYyB7DD1FshQf+mbQUGJ9HccOXNn5oHB7fWQjODjlDrYyCs7FclSMTLxA3lHX"+
"98QWeWHL2O8t8qrJQQEUWZITmr/ddiNJOOvMeYF0K5if4m84vjgx/pTwwAVyU0Yo"+
"MMXPnRozO8o7zSyRsH4jixALDugrsveEjLQI/cIEFvNjqlhyfumHyJKywNkMH1oJ"+
"4e/f89FkpeDV694lsLs1jguuLLnvroXYJ5Uzeos+F0Pj1zFDUvhWrjVwxsUfAxS8"+
"5uFGTUm6EEl9XiKwi+mgg8ODrY5dh3uE2yKB2T1Qj8BfK55zB8cYbORSsm6/f6Bi"+
"BwIDAQAB"+
"-----END PUBLIC KEY-----";
PublicKey willNotWork = decodeKey(pem);
}
My Actual Code: <- Throws exception when run on server
#Override
public PublicKey getKey() {
PublicKey pk = null;
try {
String crt = "-----BEGIN PUBLIC KEY-----"+
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvNEz3+TStAAndHTc1qwT"+
"NGvZYyB7DD1FshQf+mbQUGJ9HccOXNn5oHB7fWQjODjlDrYyCs7FclSMTLxA3lHX"+
"98QWeWHL2O8t8qrJQQEUWZITmr/ddiNJOOvMeYF0K5if4m84vjgx/pTwwAVyU0Yo"+
"MMXPnRozO8o7zSyRsH4jixALDugrsveEjLQI/cIEFvNjqlhyfumHyJKywNkMH1oJ"+
"4e/f89FkpeDV694lsLs1jguuLLnvroXYJ5Uzeos+F0Pj1zFDUvhWrjVwxsUfAxS8"+
"5uFGTUm6EEl9XiKwi+mgg8ODrY5dh3uE2yKB2T1Qj8BfK55zB8cYbORSsm6/f6Bi"+
"BwIDAQAB"+
"-----END PUBLIC KEY-----";
System.out.append("crt == " + crt);
pk = decodeKey(crt);
} catch(Exception ex){
System.out.println("getKey caught: " + ex.getMessage());
}
return pk;
}
decodeKey code:
public PublicKey decodeKey(String text) throws CryptographyException {
String content = text;
if( text.contains("-----BEGIN PUBLIC KEY-----") ) {
content = text.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
}
if( text.contains("-----BEGIN RSA PUBLIC KEY-----") ) {
content = text.replace("-----BEGIN RSA PUBLIC KEY-----", "").replace("-----END RSA PUBLIC KEY-----", "");
}
byte[] der = Base64.decodeBase64(content);
return decodeDerKey(der);
}
public PublicKey decodeDerKey(byte[] publicKeyBytes) throws CryptographyException {
try {
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKey = factory.generatePublic(
new X509EncodedKeySpec(publicKeyBytes));
return publicKey;
}
catch(Exception e) {
throw new CryptographyException(e);
}
}
Here's the exception that is thrown when I run my code on the server:
Could not parse certificate: java.io.IOException: DerInputStream.getLength():
lengthTag=111, too big`
So I am guessing is has to be some sort of difference between my laptop and the server. I have verified that both are running basically the same version of Java ("1.7.0_17"). I also checked the provider of the KeyFactory and they are the same as well. So where do I look from here?

Categories