I see there is code to read one in here
https://docs.oracle.com/javase/8/docs/api/java/security/cert/X509Certificate.html
but there is no code for writing one out.
My preference is to write a String and read a String or else I will have to base64 encode. Anyways, how to serialize it?
thanks,
Dean
Use this to write a certificate as binary
Files.write(
Paths.get(fileName),
certificate.getEncoded());
And this code will write the certificate to base64
Files.write(
Paths.get(fileName),
Base64.getEncoder().encode(certificate.getEncoded()));
If you need a PEM file, just add -----BEGIN CERTIFICATE----- header and -----END CERTIFICATE----- footer to the base64 file
Java supports reading certificates encoded in PEM or binary format
Related
I am trying to SSH to EC2 using JSch Library from Java code. I referred this link in SO How can I use .pem files content as a string in ec2 connection using JSch library and tried couple of things as mentioned below but in vain. Can someone please guide me on how to achieve my objective?
Objective
I have a PEM file like this. I dont want to store my PEM file anywhere in AWS, hence my approach is to extract an equivalent string that I can encode and store in database and decode it from java for passing the parameter to addIdentity method that takes these parameters:
addIdentity(String name, byte[] prvkey, byte[] pubkey, byte[] passphrase)
throws JSchException
-----BEGIN RSA PRIVATE KEY-----
MIIepsdfAIBAAKCAQEAtBk068z
...
xVNdhlDy6asdk9wsdQ==
-----END RSA PRIVATE KEY-----
For my objective, my addIdentity method would be like this I believe:
addIdentity ("username","{privatekey string converted to byte array}",null, null)
I am trying to understand how that string can be formed? I am very new to cryptography, but during this process I learnt that since my PEM has BEGIN RSA PRIVATE KEY, it's PKCS1 format. Does JSch support PKCS1 format or it needs to be converted to PKSC8?
Secondly, I learnt that the body is encoded with Base64, so I even tried decoding the string with Base64 after stripping off all the carriage returns, header and footer, which gave me error like this
Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
Below are some of the additional links I tried following up but have not been able to resolve.
JSch getting "invalid privatekey:" while trying to load an RSA private key by KeyPairGenerator
Java - How to decode a Base64 encoded Certificate
Converting a PEM private key file to a JAVA PrivateKey Object
Hope someone can guide me in the right direction.
Thanks!
I figured out the answer.
Below post gave me a direction.
JSch: addIdentity from private key stored on hdfs
To anyone else who is looking to solve a similar requirement, ensure that you are not stripping off the header, footer information. This took most of my time to debug as most of the blogs/SO posts directed towards stripping those characters. In Java, your string must have the carriage returns else you might get a very different byte array.
String x = "-----BEGIN RSA PRIVATE KEY-----\r\n" +
"MIIEpAIBAAKCAQEAtBk\Q/z4QAgk+LN3IUajqjUv7IucsCd4SebbQvah5t4WJ\r\n"
Convert the string to byte array using "US-ASCII" charset. Use following JSch method if you don't have a passphrase:
jsch.addIdentity("username",{bytearray of x},null, null)
Note: ensure that you are passing an unsigned byte array like:
Array (45, 45, 69,...)
and NOT
Array (45, -35, -125,...)
I know this issue may be duplicated somewhere else, but i wasted a lot of time to fix this issue.
I need to use third party API and as per their documentation i have to generate private/public key using the command ssh-keygen -t rsa, send to them the public key and for every request i must sign the request body using my private key
i found many code sample to read private/public key of formats like pem or der, but not the format generated using ssh-keygen -t rsa
my private key now is
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,07E3CD04C0D5E7AEC5BFB3660C389A79
iP+UVOT9UUma638HRLzyd9hLeZGbs2NxTakIWCB5Inpvd5+O4vcdjNhmV3zxSyDY
JpHlU8417Fyn3qHjHbG2Tj86qgFeexcZ83pjXxFU8JnXfqutSe6Zpa4sDuZYKve6
Xv2oxF64pVqEesH+C9XOkyYiWVqr09vpKBlIM2GcI2WqQwLuDYhj/AAWJhpKGVJu
+fwiQj7VS+tzBE1QW4Kva5xwEE4z/XZHkYMNDHUXBPeifsYXwkz8ZcXlcVZ+CAql
jwKh4ORXkBO/Ok2wva3dFfU7no2YSNIDhgHFGK6C9n5igbstYbTEPEH/YeSbqz1L
SucLiftfdvL9UdFb1/NQfcFhusNPHctGybvfAzttQEfSU/W5OYcN25SKF5pHUtHZ
Widu5M3JFCJ5Gw0P2sjANZVN/+8p0alT61dy6OqLckJmJfixpkvRQqdEP8ucUlTe
r+X5Fe2xH+cYh2MLq9IXxrK4g0sUZKoZw4AGKq24CfvD2K7UqHlXVO1hocyhlq+m
rRCVvRLJc7mpvpBtIQ6qXbr1chMa3zgkf6jW9thJ40jt4Giarj5s80fSC3Dk3lQN
ENV7nnhmd2uzz5yXx4sITnoDnItYDcJZk5pcOR4FAjUR2wRaLokae0pdEbS4heMa
KPOGOZGJNxs2CpwFUZL3CKIVMOmh14pzjZ4DNb9yzVhyd6wag5HlN9JNB1322eDO
lzfEnyki45wVGnB6ChthOnDRdgP5CUK+eaGqO8BSS+wttR25+MbZEwyljoQXc59h
XbGL5qqxpzrIT9+wDrEq8QNUaIg5OEXvBLa3NVOWSStgx+q5gqb5mzwJVdJiqSfL
xGG0CcyKuDPi6Vt/GKx5SGYi0gHFBs3QlYwzvvBxb5xKTc/meQSCM2ALXuJrFjBT
hXCBRBQ4F6i3pnyqkPJ36hsQ/mv6AWtsNhkMs2LrMjic0Fl5OhU6m1YA1nx8qz8k
ZQBhSWxLaTVwQsYnkH6SApPSo0t+FIzQfpnyYj4A9o6uK3dOiXPZndKqKx4mwqwM
uszlfMobhZUn2+ZcILXSZb1nNrwHKANRsp+I4j8bjG7qYKS5dfPaeIxRVQnpCkK+
SVznB0x8/EtIb8mLvuFtQap9KQ1S5UQxF3HhFoHdKjbDlEhMI3KPzURgYpis8K0y
M6jUbBnFQog9rSRCM79qE/cK6FX/QHrZt1Ijb9sPo54Y1TJQhbTempQ8N8SLnJFE
SY7W9wqOjyjrIKJ1NAWVSAHKu3ctUZHqWqijykkGa/t09BmtKoaHJ3RTJmQ7r/Z2
nxnARy9lDBSXgp8ErcYcf1eeRtCeRMZY+22F8gD7jJ/uKeEj6k8oUITt/dYSJWeA
LI9rPYydva8cNi0RtcB8Vgddi+GnhnGnhIXs3swk4AiVhBAPlAEfMdp3MjARrkJI
2UuMHStfht96aD3x3mL4fP0o6fJ5jSj/aCepwuR18xUHgtCCO8Sj81NBwPTSv654
XzIngNY3OPAOqo3RmS+xSnH8sCwE/wJxVu2sa/Ue8XszsjrzO4plYKh344MdR6g3
ISWyjPnFsdL1gBxoiPGfM/EF0bd4a1iGHDk4Ih4AcPgpgMwgN2VYDvGcxHEkQ0Y9
-----END RSA PRIVATE KEY-----
my public key
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZ98gmTkAoteabP96SmMDWAsPYIj5tV4iovMC9IEeWtiV1DbOIYVYpp27YM2DezoEuBwbccG9+A2wygyYKAVJurfmQTTL4h2WxJ5UIRJtwKrc2UKZNA6amUfIEcQHt0qJeTk6t5Havte2eTU3P6p15J7sHonLdeVBqybjeUMTOc8g41uUtTtmgTSp3BORkY/qwYzC7bICWZuuoklathRgj0CATkfkz25kggV/cNiWo8Ngr2mM8qB3EZxidF6FYwGROYRFq9jPfn1K3EvgOWWsPeHwd/bJn109sTqaLY5TsKuatxZAE+3CHNoQsEGaAVtEz505Oa8IRJYp9LERuBHx1 melad#pcwrk005.bovc.dk
how to read these files using java and sign,verify strings using them
This question already has an answer here:
Why are the RSA-SHA256 signatures I generate with OpenSSL and Java different?
(1 answer)
Closed 6 years ago.
Using this tutorial, I created a Java program what can sign a document with SHA256withRSA algorithm. In the output I get a public key and a signature file.
I try to verify my file with openssl, but I can't... I was searching on the net and I found that I need to have a standard .pem key maybe, so my question is: How can I convert my key to pem format? Or can I generate a .pem key in Java? And if it's a wrong way, how can I verify my signature?
A PEM file contains the public key binary data encoded in base64 and splitted in lines of 64 characters. The file has also the header -----BEGIN PUBLIC KEY----- and the footer -----END PUBLIC KEY-----
Java has not a native converter to PEM but you can use bouncycastle
PEMWriter pemWriter = new PEMWriter(new FileWriter(file));
pemWriter.writeObject(publicKey);
pemWriter.flush();
pemWriter.close();
Alternatively you can verify a signature with openssl using a binary key format using
-keyform DER
Then save the content of your publicKey in a file
byte publicKeyDer[] = publicKey.getEncoded()
I got a string represents PEM certificate:
-----BEGIN CERTIFICATE-----
MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL
MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC
VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx
NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD
TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu
ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j
V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj
gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA
FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE
CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS
BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE
BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju
Wm7DCfrPNGVwFWUQOmsPue9rZBgO
-----END CERTIFICATE-----
I assigned the above string to String variable String myCertStr.
What is the proper way to convert myCertStr to DER encoded byte[]?
(I am using Java 7, and I am not interested to use 3rd party library for this, I am seeking for a JDK7 way of doing it.)
IMPORTANT
As #dave_thompson_085 has pointed out in the comments, SunJCE CertificateFactory is indeed capable of parsing PEM files.
So you can just use that to get the Certificate object
as detailed at How to load public certificate from pem file..? (which is an earlier answer by #dave on the same topic, so please upvote it, instead of this one, if you find this useful !), and then access its encoded (DER) form.
However, if your PEM file is a raw "RSA PUBLIC KEY" (like the one that was attached to this question), or some other entity which SunJCE implementation can not parse directly, you can still parse and decode it manually, as detailed below.
Technically what you have here is not a certificate, but just a public key.
You can decode it to DER bytes as simple as that:
byte[] derBytes = Base64.getDecoder().decode(
pemText.replaceAll("-----(BEGIN|END) RSA PUBLIC KEY-----", "").replaceAll("\n", "")
);
Note, that what you will get will be a raw RSA (PKCS#1) key:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
You can use the same technique to decode X.509 certificates or private keys.
E.g. the code to decode the X.509 certificate:
byte[] certificateBytes = Base64.getDecoder().decode(
pemText.replaceAll("-----(BEGIN|END) CERTIFICATE-----", "").replaceAll("\n", "").getBytes("UTF-8")
);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)(certificateFactory.generateCertificate(
new ByteArrayInputStream(certificateBytes)
)
);
UPDATE
The code above uses Java 8 Base64 decoder.
As question has been updated asking for a Java 7 solution,
here is a link to an excellent thread, discussing various options available: Base64 Java encode and decode a string.
E.g. java.xml.bind method described there does not require any extra libraries on Java 7 (which seems to match what OP wants)
I am trying to detect the content of a PEM file. In case it contains certificate infos, the following code is perfect to get X509Certificates informations:
X509Certificate cert = X509CertUtils.parse(Files.readAllBytes(file.toPath()));
but returns NULL of course if it's a key instead of certificate.
So is there a proper way to detect PEM content (mayb PEMReader and then instance of on the result. I tried with a ---- PRIVATE KEY ----- file but it returned null also)?
Of course, I can manually detect if file contain -----BEGIN CERTIFICATE----- or -----BEGIN PRIVATE KEY----- but I find this very careless.
Thank you !