How do I read an sha1WithRSAEncryption public DER key in Java? - java

openssl x509 -inform DER -text
on my DER file gives the dump on the bottom of this question.
I try to read it with:
static PublicKey getCertKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
URL keyUrl = Resources.getResource(LManager.class, "iid.der");
byte[] keyBytes = Resources.toByteArray(keyUrl);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
And I get:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
....
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Caused by: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
at sun.security.x509.X509Key.decode(X509Key.java:397)
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)
... 25 more
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
a9:cb:e1:41:03:30:df:c5
Signature Algorithm: sha1WithRSAEncryption
Issuer: REDACTED
Validity
Not Before: Jun 5 14:28:02 2014 GMT
Not After : Jun 5 14:28:02 2024 GMT
Subject: REDACTED
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:87:bd:18:df:ff:49:12:b6:92:76:e3:c9:21:b4:
86:8d:f2:a9:03:37:7b:64:c3:85:63:bc:0f:67:bc:
f9:76:6a:72:4e:f9:e2:01:52:a3:df:40:6d:3d:91:
99:70:a5:6a:66:c8:ef:1b:18:1d:91:5a:a5:b1:0b:
0b:81:fd:d7:27:22:86:fa:c3:8d:b4:93:d5:98:e4:
2d:08:20:6b:43:44:d6:ae:37:79:2e:bc:65:e4:c3:
71:c4:9c:5d:04:8d:8a:f4:a5:cc:96:52:f0:72:59:
8e:0a:b3:06:55:e3:65:fb:63:b5:d2:4b:5d:e1:38:
87:0b:e8:d2:c0:f8:7f:78:fd
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
25:D6:CC:08:15:CA:B6:F0:9C:59:DC:14:52:2C:EF:B5:41:76:51:38
X509v3 Authority Key Identifier:
keyid:25:D6:CC:08:15:CA:B6:F0:9C:59:DC:14:52:2C:EF:B5:41:76:51:38
DirName:/C=US/ST=Washington/L=Seattle/O=Amazon.com Inc./CN=ec2.amazonaws.com
serial:A9:CB:E1:41:03:30:DF:C5
X509v3 Basic Constraints:
CA:TRUE

First, openssl -inform DER -text is an error. The openssl program is a wrapper that runs one of a bunch of functions, identified by the first argument, which in this case must be x509, so openssl x509 -inform DER -text.
That's a clue. Your file is an X.509 certificate not (just) a public key. Certificates in general, and X.509 certificates in particular, contain a public key but that is not the same thing as being a public key.
Since your file is an X.509 certificate, use a CertificateFactory of type X.509 to read it. The pattern is similar: use a static .getInstance() method to get a factory then use .generateCertificate() to take some input, here a stream that reads the data (directly from the file, or from memory if you have it buffered), and generate a Certificate object. (Note java.security.cert.Certificate not the obsolete and deprecated java.security.Certificate -- some IDEs may not default to the good one.)
If you want to use the public key in the certificate for something like encrypting or verifying call .getPublicKey() on the Certificate. If you want to look at other information such as the subject name or extensions which are specific to X.509, cast the Certificate to X509Certificate (also in java.lang.security.cert) and use its additional methods.
Also: the certificate is signed with sha1withRSA. The publickey itself is an RSA key, and could be used for any RSA operation -- but since the cert claims this key belongs to a CA, the corresponding privatekey should be used only for signing certs and/or CRLs (controlled by KeyUsage if present, but it's not unless you've redacted it) and thus doing something with this publickey other than verifying those certs and/or CRLs is useless. And since the key is only 1024 bits, using a signing hash stronger than SHA1 would be wasted, except for the facts that RSA-1024 is already considered insecure (since early 2014) and using SHA1-RSA for certificates is considered at risk and prohibited after sometime next year.

Related

Generate self-signed certificate and create keystore and generate JWT token in Java

I am trying to generate a jwt token from a keystore.
For this I downloaded "openssl-for-windows" https://code.google.com/archive/p/openssl-for-windows/downloads
Run the following commands in the command prompt as an administrator.
CLI comnd
Creating a sample CA certificate
openssl.exe req -config openssl.cnf -new -x509 -keyout private.pem -out certificate.pem -days 365
Create a kestore named keystore
keytool –keystore keystore –genkey –alias client -keyalg rsa
Generate certificate signing request
keytool –keystore keystore –certreq –alias client –keyalg rsa –file client.csr
Generate signed certificate for associated CSR
openssl.exe x509 -req -CA certificate.pem -CAkey private.pem -in client.csr -out client.cer -days 365 -CAcreateserial
Import CA certificate into keystore
keytool -import -keystore keystore -file certificate.pem -alias theCARoot
Import signed certificate for associated alias in the keystore
keytool –import –keystore keystore –file client.cer –alias client
Next, I created a java code to generate a token.
Main.java
public class StreamKey {
public static void main(String[] args) {
StreamKey key = new StreamKey();
key.getSer();
}
private void getSer() {
try {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("clientkeystore");
char[] password = "111111".toCharArray();
String alias = "client";
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(inputStream, password);
Key key = keyStore.getKey(alias, password);
LocalDateTime currentTime = LocalDateTime.now();
Date dat = Date.from(currentTime.plusMinutes(5).atZone(ZoneId.systemDefault()).toInstant());
Map<String, Object> claims = new HashMap<>();
claims.put("sub", alias);
claims.put("exp", dat.getTime());
String token = Jwts.builder()
.setHeaderParam("alg", "RS256")
.setHeaderParam("typ", "jwt")
.setClaims(claims)
.signWith(key, SignatureAlgorithm.RS256).compact();
System.out.println(token);
} catch (IOException | KeyStoreException | CertificateException | NoSuchAlgorithmException |
UnrecoverableKeyException e) {
throw new RuntimeException(e);
}
}
}
After creating the token, I went to the site https://jwt.io/ and pasted this token into the "Encoded PASTE A TOKEN HERE" field, then I opened the client.csr file in a text editor and copied the contents and pasted it into the "Public Key" field ".
After these steps, "Invalid Signature" is still highlighted in red
But if I take the content from the private.pem file and paste it into the "Private Key" field, then "Invalid Signature" is highlighted in blue.
The question is why when I use the public key, "Invalid Signature" is highlighted in red?
I took all the material from YouTube.
Man creates keys https://www.youtube.com/watch?v=nxowUHao9TI
The same person creates a jwt token using java https://www.youtube.com/watch?v=MWlDQaR-LLM
https://github.com/MyTestPerson/rsa-jwt
LOG
D:\test\openssl-0.9.8k_X64>.\bin\openssl.exe req -config openssl.cnf -new -x509 -keyout private.pem -out certificate.pem -days 365
Loading 'screen' into random state - done
Generating a 1024 bit RSA private key
........................++++++
..++++++
writing new private key to 'private.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:qq
State or Province Name (full name) [Some-State]:ww
Locality Name (eg, city) []:ee
Organization Name (eg, company) [Internet Widgits Pty Ltd]:rr
Organizational Unit Name (eg, section) []:tt
Common Name (eg, YOUR name) []:yy
Email Address []:uu
D:\test\openssl-0.9.8k_X64>keytool -keystore keystore -genkey -alias client -keyalg rsa
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: uu
What is the name of your organizational unit?
[Unknown]: yy
What is the name of your organization?
[Unknown]: tt
What is the name of your City or Locality?
[Unknown]: rr
What is the name of your State or Province?
[Unknown]: ee
What is the two-letter country code for this unit?
[Unknown]: ww
Is CN=uu, OU=yy, O=tt, L=rr, ST=ee, C=ww correct?
[no]: yes
Generating 2 048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 90 days
for: CN=uu, OU=yy, O=tt, L=rr, ST=ee, C=ww
D:\test\openssl-0.9.8k_X64>keytool -keystore keystore -certreq -alias client -keyalg rsa -file client.csr
Enter keystore password:
D:\test\openssl-0.9.8k_X64>.\bin\openssl.exe x509 -req -CA certificate.pem -CAkey private.pem -in client.csr -out client.cer -days 365 -CAcreateserial
Loading 'screen' into random state - done
Signature ok
subject=/C=ww/ST=ee/L=rr/O=tt/OU=yy/CN=uu
Getting CA Private Key
Enter pass phrase for private.pem:
D:\test\openssl-0.9.8k_X64>keytool -import -keystore keystore -file certificate.pem -alias theCARoot
Enter keystore password:
Owner: EMAILADDRESS=uu, CN=yy, OU=tt, O=rr, L=ee, ST=ww, C=qq
Issuer: EMAILADDRESS=uu, CN=yy, OU=tt, O=rr, L=ee, ST=ww, C=qq
Serial number: a51a542a98afc4c9
Valid from: Sun Aug 14 17:33:41 SAKT 2022 until: Mon Aug 14 17:33:41 SAKT 2023
Certificate fingerprints:
SHA1: 45:E2:09:05:60:D6:AA:5A:21:6E:58:F3:4D:12:1E:85:14:1C:B8:7C
SHA256: 80:A5:C6:19:6B:F0:14:F0:9C:0F:8D:C0:80:96:AF:12:F7:6A:E3:25:F0:81:55:ED:32:52:BD:71:2D:5E:E9:38
Signature algorithm name: SHA1withRSA (weak)
Subject Public Key Algorithm: 1024-bit RSA key (weak)
Version: 3
Extensions:
#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 04 BA 9F 89 CE E3 9C 37 C8 0B 36 86 68 55 BD 5D .......7..6.hU.]
0010: CA 17 80 22 ..."
]
[EMAILADDRESS=uu, CN=yy, OU=tt, O=rr, L=ee, ST=ww, C=qq]
SerialNumber: [ a51a542a 98afc4c9]
]
#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen: no limit
]
#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 04 BA 9F 89 CE E3 9C 37 C8 0B 36 86 68 55 BD 5D .......7..6.hU.]
0010: CA 17 80 22 ..."
]
]
Warning:
The input uses the SHA1withRSA signature algorithm which is considered a security risk. This algorithm will be disabled in a future update.
The input uses a 1024-bit RSA key which is considered a security risk. This key size will be disabled in a future update.
Trust this certificate? [no]: yes
Certificate was added to keystore
D:\test\openssl-0.9.8k_X64>keytool -import -keystore keystore -file client.cer -alias client
Enter keystore password:
Certificate reply was installed in keystore
Warning:
Issuer <thecaroot> uses a 1024-bit RSA key which is considered a security risk. This key size will be disabled in a future update.
The input uses the SHA1withRSA signature algorithm which is considered a security risk. This algorithm will be disabled in a future update.
D:\test\openssl-0.9.8k_X64>

How do I convert a binary certificate to x509?

I have a server certificate that I want to trust. But java doesn't accept it in this code. How do I convert the certificate to x509?
return (Collection<X509Certificate>) CertificateFactory.getInstance("X.509")
.generateCertificates(new ByteArrayInputStream(cert.getBytes()));
cert:
0‚я0‚з \±
®FPљF·1ЪуAяф0
*†H†ч
0Ѓ•10 UGB10UGreater Manchester10USalford10U
Sectigo Limited1=0;U4Sectigo RSA Organization Validation Secure Server CA0
210913000000Z
221014235959Z0e10 URU10
UMoskva10U
PJSC MTS Bank10 UIT1 0Utestpayments.mtsbank.ru0‚"0
†H†ч
‚ 0‚
‚ БLR€fЁВGK}ЧІЅџ¬‡ »FйЎNлNЕї¦жШЪvДhг,Чb‘ђ‰(фњkЬ4эµoµQS¶4¦9
0bц±€ks%®xЇҐ4ўжк¦…ФnДF†Ж]b{L|Ш7’ЪmIЈvўДЉ„ym¶T\ьЛСx)Ѓ€~х’Ѓiр·юЎKЦfРћ'-ѓКђђЂ)И;\ЙБ/ФфЂ&C®¤Л
°‚M;щн_ 1~#JЅJРЯЖЈ1Ю•н)Ќµdґnы–оШ9:4њSН¬ъИЊ­ь.уЈ8чІ  ИЄФ9йѕфqj–Эао=KДњX%Р§я~A7± Ј‚x0‚t0U#0ЂЩЦ%'gщ1ВICЩ06DЊl©Oл0UзEКЁуІ‡Sґ«&›И 9 S :50Uя 0Uя0 0U%0++0JU C0A05+І10%0#+https://sectigo.com/CPS0gЃ0ZUS0Q0O M K†Ihttp://crl.sectigo.com/SectigoRSAOrganizationValidationSecureServerCA.crl0ЃЉ+~0|0U+0†Ihttp://crt.sectigo.com/SectigoRSAOrganizationValidationSecureServerCA.crt0#+0†http://ocsp.sectigo.com0?U806‚testpayments.mtsbank.ru‚www.testpayments.mtsbank.ru0‚} +Цy‚m‚ig u FҐUлuъ‘ 0µў‰iфу},AtѕэIё…«тьpюmG {Ю|ъ] F0D &я$„ѕT<ЎюЯC jД‘ћDЇ‚вЕЏWјV}д °Љ)n›мРДtщq©,mІGќеЬ–Pjп–®e v AИК±Я"FJЖЎ: B‡^N1‹ллKЗhрђb–ц {Ю|ъ" G0E! Я55eЮьэW;ыФ/µр·ћІNцw*\¤OGќ
M 50МЖіT{жМ‘П=ЧНHэД9v‚UOеСуЧ$ v )yѕрћ99!рVsџcҐwеѕW}њ шщM]&\%]З„ {Ю|щэ G0E gЫx;·ґш1шнГ*Z“ЬЄЪ2ы••vIоhЮ! чxтЁ‹Е–ќµ\©mШ= 6ўчеЧ{Ўь:кё6лЄг0
†H†ч
‚ Ћz™ЋQZп^чZVеVцOS;‰?Њ4Щї;Д8?•1ЫА:rZўПгdфИ zTдt3¦СЊҐБ™»g[R¦oаOH;¬Ъw{†хІDuљ,1Кc­ЂЂ5НAR
6СаГ ќщџэБДСЊ-ё“fќCs’ПСЫ%иаѕ‹[5с|Т~FН§b4эKйЃ39&нџЫ’Т2>Щид8”Ќtп9–-bўоbRі›]Љ9аNgцЄ7.ЁOЯ[)©Фµх. ®тмҐ{µ¦`·|оьуР¬]сЂІv9ЋWХH›xаrЁУя»zЛ_рJ.З;yS#}Ё
I tried to do so but failed:
OpenSSL> x509 -in Z:\cert.cer -out Z:\cert12.pem
unable to load certificate
10976:error:0906D06C:PEM routines:PEM_read_bio:no start line:crypto\pem\pem_lib.c:686:Expecting: TRUSTED CERTIFICATE
error in x509
Encoded in base64 through the file and the code passed
https://www.base64encode.org/

Dropwizard Client Certificate Authentication via HttpClient Key/Trust store

I am running a dropwizard server, and a client leveraging Apache HttpClient 4.5.1.
Given a single .pfx file that contains both the public and private keys, how would I structure my key/trust stores on both the server and client to accept/trust and pass the certificate for authentication purposes?
What I'm running into is the client trusts the provided server certificate, but
after the server hello that includes the certificate request per tls spec, my client is unable to find a suitable certificate to send back.
My first thought was to run the server with the keystore and truststore as the same pfx file, but java throws a null cert chain error when loading the pfx file as a trust store in the server. So I had to go through the process of creating a trust store manually.
Here are the general steps I thought would allow this entire process to succeed:
Run the server with the .pfx file, with a PKCS12 keystore type.
Extract the cert from the pfx file, and create a java trust store using the cert.
Run the server with the above clientCerts.jks file as the trust store
Run the client with a keystore set to the clientCerts.jks file
Run the client with a truststore set to the .pfx PKCS12 keystore.
These steps didn't work, and I've tried other less obvious permutations and none of them worked. Is there something blatantly wrong with the way I'm approaching this? Does anyone have any advice on actually getting it to work?
Lots of details below (including ssl debug logs)
PFX cert info:
(its a valid corporate signed cert, but I don't have the root CA as trusted anywhere, which is why I just create a trust store so I can trust the client cert).
$ openssl pkcs12 -info -in cert.pfx
Enter Import Password:
MAC Iteration 1
MAC verified OK
PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2000
Bag Attributes
Microsoft Local Key set: <No Values>
localKeyID: 01 00 00 00
friendlyName: xxx
Microsoft CSP Name: Microsoft RSA SChannel Cryptographic Provider
Key Attributes
X509v3 Key Usage: 10
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----BEGIN ENCRYPTED PRIVATE KEY-----
xxx
-----END ENCRYPTED PRIVATE KEY-----
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2000
Certificate bag
Bag Attributes
localKeyID: 01 00 00 00
friendlyName: my.domain.com
subject=/C=US/O=My Company/OU=Web Servers/CN=my.domain.com
issuer=/C=US/O=My Company
-----BEGIN CERTIFICATE-----
xxx
-----END CERTIFICATE-----
Java Trust store Creation:
//create pem file
openssl pkcs12 -in cert.pfx -out tempCert.crt -nokeys -clcerts
//convert to x509
openssl x509 -inform pem -in tempCert.crt -outform der -out tempx509Cert.cer
//create a java trust store
keytool -import -file tempx509Cert.cer -alias firstCA -keystore newJavaTrustStore.jks
Dropwizard Config:
applicationConnectors:
- type: https
port: 443
bindHost: localhost
keyStorePath: ./cert.pfx
keyStorePassword: pw
keyStoreType: PKCS12
trustStorePath: ./clientCerts.jks
trustStorePassword: pw
trustStoreType: JKS
supportedProtocols: [TLSv1, TLSv1.1, TLSv1.2]
excludedProtocols: [SSLv2Hello, SSLv3]
validateCerts: false
needClientAuth: true
wantClientAuth: true
HttpClient Config Values:
keyStorePath: ./clientCerts.jks
keyStorePassword: pw
keyStoreType: JKS
trustStorePath: ./cert.pfx
trustStorePassword: pw
trustStoreType: PKCS12
HttpClient Config:
public static CloseableHttpClient getSecurePooledHttpClient(
final String host,
final int port,
final boolean ssl,
final String keystorePath,
final String keystorePassword,
final String keystoreType,
final String trustStorePath,
final String trustStorePassword,
final String trustStoreType
) throws Exception {
//Setup the keystore that will hold the client certificate
KeyStore ks = KeyStore.getInstance(keystoreType);
ks.load(new FileInputStream(new File(keystorePath)),
keystorePassword.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keystorePassword.toCharArray());
//Setup the Trust Store so we know what certificates
//we can trust that are hosting the service
KeyStore ts = KeyStore.getInstance((trustStoreType));
ts.load(new FileInputStream(new File(trustStorePath)),
trustStorePassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
//setup our SSL context to be TLSv1.2, then setup the key and trust manager.
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
//Register the socket factory so that it uses the ssl Context and key
// manager we created above
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE))
.build();
//Define an overridden routeplanner that setups up our default host
// so all our later calls can simply be
//sub-routes.
HttpRoutePlanner routePlanner =
new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE)
{
#Override
public HttpRoute determineRoute(
final HttpHost target,
final HttpRequest request,
final HttpContext context) throws HttpException {
return super.determineRoute(
target != null ? target : new HttpHost(host, port, ssl ? "https" : "http"),
request, context);
}
};
return BuildClientWithRoutePlanner(socketFactoryRegistry, routePlanner);
Client SSL debug:
...
*** ServerHello, TLSv1.2
RandomCookie: Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Initialized: [Session-7, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256]
** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=my.domain.com, OU=Web Servers, O=My Company, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
.........
***
Found trusted certificate:
[
[
Version: V3
Subject: CN=my.domain.com, OU=Web Servers, O=My Company, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
......
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
Cert Authorities:
<CN=my.domain.com, OU=Web Servers, O=My Company, C=US>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***

Using Java 7 to Verify OpenSSL Generated S/MIME Digital Signature Files

We have a process that uses OpenSSL to generate S/MIME digital signatures which need to be verified later using Java 7. On one side we use OpenSSL to read in text files and generate a signed digital output which is verified later.
We used to have the verification using OpenSSL but now we need Java (note: we cannot count on OpenSSL being available now).
We use this to sign: openssl smime -sign -inkey private.key -signer public.key -in ${f} > ${f}.signed and this to verify: openssl smime -verify -noverify -in ${f}.signed
Note: that the verify does not validate the certificates, only checks the signature/contents.
I need to change the verify part of this process to be a java application, preferably with Java 7 (which I think now has the JCE built in).
A sample output is something like ...
MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----185C6C544BB34D30B0835B915C158544"
This is an S/MIME signed message
------185C6C544BB34D30B0835B915C158544
Four score and seven years ago our fathers brought forth on this continent, a
new nation, conceived in Liberty, and dedicated to the proposition that all
men are created equal.
Now we are engaged in a great civil war, testing whether that nation, ...
------185C6C544BB34D30B0835B915C158544
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
MIIKAAYJKoZIhvcNAQcCoIIJ8TCCCe0CAQExDzANBglghkgBZQMEAgEFADALBgkq
hkiG9w0BBwGgggchMIIHHTCCBgWgAwIBAgIEUzuEpzANBgkqhkiG9w0BAQsFADCB
hzELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEoMCYGA1UE
CxMfRGVwYXJ0bWVudCBvZiBIb21lbGFuZCBTZWN1cml0eTEiMCAGA1UECxMZQ2Vy
dGlm ...
... JIQeeE=
------185C6C544BB34D30B0835B915C158544--
The signature algorithm is sha256WithRSAEncryption; example ...
openssl smime -pk7out -in message.signed | openssl pkcs7 -text -noout -print_certs
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1396409511 (0x533b84a7)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Corp, OU=Acme, OU=CA
Validity
Not Before: May 16 15:27:56 2014 GMT
Not After : May 16 15:57:56 2015 GMT
Subject: C=US, O=Corp, OU=Acme, OU=CBP, CN=foo.acme.corp.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:00:00:00:00:b1:b6:49:6e:ca:d7:61:07:a0:18:
...
c9:de:ab:a7:2f:97:e4:f6:64:37:ec:3a:9d:ae:c0:
16:03
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Certificate Policies:
Policy: 2.16.840.1.101.3.2.1.3.8
...
I have looked at many, many examples, tried multiple ones without success. I wish had had some source to share with you, but the success I have had so far would not be helpful in the least.
This can be done using the Bouncy Castle Crypto APIs where you can use the following official example as reference, https://github.com/bcgit/bc-java/blob/master/mail/src/main/java/org/bouncycastle/mail/smime/examples/ValidateSignedMail.java.
For a simpler example to perform a full validation of a signed email including the certification chain you would do something like this with org.bouncycastle:bcmail-jdk15on:1.52:
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.mail.smime.validator.SignedMailValidator;
import javax.mail.internet.MimeMessage;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.PKIXParameters;
public class SignedMailValidatorExample {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
FileInputStream signedEmailInputStream = new FileInputStream("signed_email.eml");
MimeMessage signedEmailMimeMessage = new MimeMessage(null, signedEmailInputStream);
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("truststore.jks"), "changeit".toCharArray());
PKIXParameters pkixParameters = new PKIXParameters(trustStore);
pkixParameters.setRevocationEnabled(false);
SignedMailValidator signedMailValidator = new SignedMailValidator(signedEmailMimeMessage, pkixParameters);
boolean successfulValidation = true;
for (SignerInformation signerInformation : signedMailValidator.getSignerInformationStore().getSigners()) {
SignedMailValidator.ValidationResult signerValidationResult = signedMailValidator
.getValidationResult(signerInformation);
if (!signerValidationResult.isValidSignature()) {
successfulValidation = false;
break;
}
}
if (successfulValidation) {
System.out.println("Signed email validated correctly.");
} else {
System.out.println("Signed email validation failed.");
}
}
}
Where truststore.jks should contain a CA certificate (e.g. the issuing CA) that chains to the certificate used to sign the email. Now, you can easily created this file using a software like https://keystore-explorer.org/.

Encryption and Decryption with X.509 public certificate

I want to encrypt my post payload with an X.509 certificate and the inherited public key. So far I have this java code to perform the encryption
private String encrypt(String str) throws Exception {
ClassPathResource classPathResource = new ClassPathResource("testcert1.crt");
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)certificateFactory.generateCertificate(classPathResource.getInputStream());
PublicKey pk = certificate.getPublicKey();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(Cipher.ENCRYPT_MODE, pk);
return Base64.encodeBase64String(cipher.doFinal(str.getBytes()));
}
which returns the base64 encoded string. From the endpoint I am always getting the result, that the certificate is not valid.
So I want to validate my encrypted string on the console using the openssl command, but failing to do so.
I can read out the certificate with: openssl x509 -in testcert1.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0 (0x0)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=xxx, ST=xxx, L=xxx, O=xxx, OU=xxx, CN=xxx
Validity
Not Before: Jul 24 11:40:39 2013 GMT
Not After : Jul 24 11:40:39 2015 GMT
Subject: C=xxx, ST=xxx, L=xxx, O=xxx, OU=xxx, CN=xxx
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (4096 bit)
Modulus (4096 bit):
....
Exponent: 65537 (0x10001)
But I cannot figure out the command lines to encrypt/decrypt a text file using that certificate
You can validate your encrypted string using openssl with the following command:
echo -n 'string to encrypt' | openssl rsautl -encrypt -certin -inkey testcert1.crt | base64
As you are using asymmetric cryptography, if you encrypt using the public key of your certificate, you can only decrypt using the corresponding private key. Make sure you have that key and use it for decryption.

Categories

Resources