sha256 hash from public key - java

I am trying to read sha256 has from a public key certificates. The certificate is shown below.
I am running following command to read sha256 hash but it is not giving proper result:
openssl x509 -in test.crt -pubkey -noout | openssl rsa -pubin -outform der | \
openssl dgst -sha256 -binary | openssl enc -base64
I am getting some wrong value RTy7aSpufwRDWUudgZCwR5Xc7NETd6Imk4YlzvgKTRU=
Correct values are:
sha256/i1RfARNCYn9+K3xmRNTaXG9sVSK6TMgY9l8SDm3MUZ4=
sha256/7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=
sha256/h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=
I am wondering how three values came in, yes only one is correct but to validate these values i do run sample program given below:
public class Main {
public static void main(String[] args) throws IOException {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
String hostName = "www.google.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostName, "sha256/pqrmt")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(interceptor)
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://" + hostName)
.build();
client.newCall(request).execute();
}
}
Adding wrong key hash give me proper one on error logs, and using proper one allows me to communicate with ease.
-----BEGIN CERTIFICATE-----
MIIISDCCBzCgAwIBAgIILbxyxVw1oQAwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTcwODAyMTk0NTM5WhcNMTcxMDI1MTkyMzAw
WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5n
b29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvqjgh7NP
S0DNdmqg94u9ecHsxtCCNH5K7RQDbT7stPZaftCBuCXEDbhmqP44ne7kKkKyHqVx
OxzDyMrvMly/qDvd17X33kXjEdte3YOWTENQ7R//LIQ2qwxOCd7LcDhRLnbhV61k
yDJIPzjM79BX8b0u9+e2KAYfhYFANB+iZrk0/sLXmlv+T+E1bm4D19H55BstEPM8
SOTUj0cntYaN+5Rcy1s9p5CjWb1Sy/JXyBv+QLkrbj2JyQ+KlG2Fil4ue3ooF2iA
LZM+k2OgCizz5Kh6za1oKkL08/wJCaqHQJMhxX1ajXW93DwyojOqt40+6tF43rEU
Uxy87Joi+ZZNOQIDAQABo4IFFTCCBREwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMIID4QYDVR0RBIID2DCCA9SCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk
LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYISKi5jbG91ZC5nb29nbGUuY29t
ghQqLmRiODMzOTUzLmdvb2dsZS5jboIGKi5nLmNvgg4qLmdjcC5ndnQyLmNvbYIW
Ki5nb29nbGUtYW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xlLmNs
gg4qLmdvb2dsZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNvLnVr
gg8qLmdvb2dsZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUuY29t
LmJygg8qLmdvb2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29nbGUu
Y29tLnRygg8qLmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2dsZS5l
c4ILKi5nb29nbGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5nb29n
bGUubmyCCyouZ29vZ2xlLnBsggsqLmdvb2dsZS5wdIISKi5nb29nbGVhZGFwaXMu
Y29tgg8qLmdvb2dsZWFwaXMuY26CFCouZ29vZ2xlY29tbWVyY2UuY29tghEqLmdv
b2dsZXZpZGVvLmNvbYIMKi5nc3RhdGljLmNugg0qLmdzdGF0aWMuY29tggoqLmd2
dDEuY29tggoqLmd2dDIuY29tghQqLm1ldHJpYy5nc3RhdGljLmNvbYIMKi51cmNo
aW4uY29tghAqLnVybC5nb29nbGUuY29tghYqLnlvdXR1YmUtbm9jb29raWUuY29t
gg0qLnlvdXR1YmUuY29tghYqLnlvdXR1YmVlZHVjYXRpb24uY29tggcqLnl0LmJl
ggsqLnl0aW1nLmNvbYIaYW5kcm9pZC5jbGllbnRzLmdvb2dsZS5jb22CC2FuZHJv
aWQuY29tghtkZXZlbG9wZXIuYW5kcm9pZC5nb29nbGUuY26CHGRldmVsb3BlcnMu
YW5kcm9pZC5nb29nbGUuY26CBGcuY2+CBmdvby5nbIIUZ29vZ2xlLWFuYWx5dGlj
cy5jb22CCmdvb2dsZS5jb22CEmdvb2dsZWNvbW1lcmNlLmNvbYIYc291cmNlLmFu
ZHJvaWQuZ29vZ2xlLmNuggp1cmNoaW4uY29tggp3d3cuZ29vLmdsggh5b3V0dS5i
ZYILeW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29tggV5dC5iZTBoBggr
BgEFBQcBAQRcMFowKwYIKwYBBQUHMAKGH2h0dHA6Ly9wa2kuZ29vZ2xlLmNvbS9H
SUFHMi5jcnQwKwYIKwYBBQUHMAGGH2h0dHA6Ly9jbGllbnRzMS5nb29nbGUuY29t
L29jc3AwHQYDVR0OBBYEFJsK+1wBuADqH695FkUxvBBxBD13MAwGA1UdEwEB/wQC
MAAwHwYDVR0jBBgwFoAUSt0GFhu89mi1dvWBtrtiGrpagS8wIQYDVR0gBBowGDAM
BgorBgEEAdZ5AgUBMAgGBmeBDAECAjAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8v
cGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQCWfamc
vElR0WkzwdaofPD66PsmqihYbgMAEOJBtt4isDLcVqG0tE8xwAYZO+EksklR6nXq
Pi8021W/qgh2XDmyGajc/psjSBdfAi2bw/kIMcXpQsJSR33n0kLJe4/5z5YwSJEt
M7f6DKlBzxalGrHc2rnkOw4xZEKYZ+nJQ5E3Lms0NKHFPxj3c5QvUYfiWhC4lY1m
RZRPIDQc9Bmcu+gJseRGYd8g+USo0829CMq42KaQM7nshxmwexXPv9ic9nV6f+Qi
nw1hL6RdI3+yHRSZCBPnlfpQfLLJatJmpwddP2ibT56zDDT4BQsP4/QeAbEOJ+Bp
0nJ0S+1OpCbjQXYL
-----END CERTIFICATE-----

sha256/i1RfARNCYn9+K3xmRNTaXG9sVSK6TMgY9l8SDm3MUZ4=
This pin matches the leaf certificate returned when accessing www.google.com:
$ openssl s_client -connect www.google.com:443 |\
openssl x509 -pubkey -noout |\
openssl pkey -pubin -outform der |\
openssl dgst -sha256 -binary |\
openssl enc -base64
...
depth=0 ... CN = www.google.com
i1RfARNCYn9+K3xmRNTaXG9sVSK6TMgY9l8SDm3MUZ4=
But, if you have a closer look at the certificate returned when accessing www.google.com you see that is has a CN of www.google.com. Instead the certificate you've included in your question has a CN of *.google.com, i.e. is a different certificate. This certificate is returned for example if you access google.com instead of www.google.com:
$ openssl s_client -connect google.com:443 |\
openssl x509 -pubkey -noout |\
openssl pkey -pubin -outform der |\
openssl dgst -sha256 -binary |\
openssl enc -base64
...
depth=0 ... CN = *.google.com
RTy7aSpufwRDWUudgZCwR5Xc7NETd6Imk4YlzvgKTRU=
As you can see, the public key fingerprint you had computed was the correct one. Only your assumptions about the correct fingerprints where incorrect because you've checked these against the wrong site.

Related

How to configure Web client for Https request

I am trying to understand how to configure the Web client. What I have is a working curl that I am not able to convert into a valid HTTPS request through (any) Java HTTP client.
The curl is:
curl -s --cert $CERTIFICATE --key $KEY https.url
where $CERTIFICATE is a .crt file containing:
----BEGIN CERTIFICATE----
....
----END CERTIFICATE-----
And the $KEY is a .key file containing:
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
I want to convert this curl into a valid JAVA request. Currently, I am configuring a Spring WebClient in this way:
private WebClient getWebClient() throws SSLException {
SslContext sslContext = SslContextBuilder.forClient().keyManager(
Paths.get(properties.getCrtFile()).toFile(),
Paths.get(properties.getKeyFile()).toFile(),
properties.getCertKeyPassword()).build();
HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext));
return WebClient
.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient)).build();
}
But when I use the webclient to make a request it returns an error:
exception: File does not contain valid private key:
Any idea where is the error?
This is how I solved the problem:
Verify that .cert and .key files are valid:
openssl x509 -noout -modulus -in certFile.crt | openssl md5
#> (stdin)= 7f1a9c4d13aead7fd4a0f241a6ce8
and
openssl rsa -noout -modulus -in certKey.key | openssl md5
#> (stdin)= 7f1a9c4d13aead7fd4a0f241a6ce8
Convert my .cert and .key files into a PCKS12 that Java can understand. (Keep in mind that my cert and key files are in PEM format as explained in the question). I used the following command:
openssl pkcs12 -export -in certFile.crt -inkey keyFile.key -out cert.p12
This step will prompt you to enter a password. We will use this password when reading the certificate into a KeyStore.
Create an SSLContext by reading the certificate:
private SslContext getSSLContext() {
try (FileInputStream keyStoreFileInputStream = new
FileInputStream("pathTop12CertificateFile")) {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyStoreFileInputStream,"password".toCharArray());
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, "password".toCharArray());
return SslContextBuilder.forClient()
.keyManager(keyManagerFactory)
.build();
} catch (Exception e) {
log.error("An error has occurred: ", e);
}
return null;
}
Build a Spring WebClient using this SSLContext:
private WebClient getWebClient() {
HttpClient httpClient = HttpClient.create().secure(sslSpec -> sslSpec.sslContext(getSSLContext()));
ClientHttpConnector clientHttpConnector = new ReactorClientHttpConnector(httpClient);
return WebClient
.builder()
.clientConnector(clientHttpConnector)
.build();
}
Now we can use WebClient to make our HTTP Requests.
From the details you provided, I understand that the SslContextBuilder can't understand your key type.
Try to convert a non-encrypted key to PKCS8 using the following command.
openssl pkcs8 -topk8 -nocrypt -in pkcs1_key_file -out pkcs8_key.pem
Also, see the examples at https://netty.io/4.0/api/io/netty/handler/ssl/util/InsecureTrustManagerFactory.html that accepts without verification all X.509 certificates, including those that are self-signed.
Also discussed at https://groups.google.com/forum/#!topic/grpc-io/5uAK5c9rTHw

Java equivalent to 'openssl rsautl -verify -out'

I have some data which has been signed using something like the following:
openssl rsautl -sign -in file -inkey PrivateKey.pem -out sig
The signed data can then be recovered using the following:
openssl rsautl -pubin -inkey PublicKey.pem -verify -in sig -out file
I've converted the public key into a Java PublicKey object and looked at using that with the Signature class in java.security, but that doesn't appear to have a method that allows recovering the original signed data.
Is there a way to recover the signed data using Java?
As suggested in the comment by dave_thompson_085, the following can be used to recover the data:
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] extractedBytes = cipher.doFinal(sig);

Can't decrypt RSA data with open SSL

I try to encrypt some data in matlab using a public key I created with openssl
I created the keys using:
openssl genrsa -des3 -out private.pem 1024
openssl rsa -in private.pem -pubout -outform DER -out public.der
I encrypt my data using this matlab code (with Java libraries):
import java.security.spec.RSAPublicKeySpec
import javax.crypto.Cipher;
import java.security.KeyFactory
import java.math.BigInteger
fid = fopen('public.der');
a = fread(fid);
key = java.security.spec.X509EncodedKeySpec(a);
kf = KeyFactory.getInstance('RSA');
KEY = kf.generatePublic(key);
cipher = Cipher.getInstance('RSA/ECB/PKCS1Padding');
cipher.init(Cipher.ENCRYPT_MODE, KEY)
plaintextBytes = [24];
ciphertext = cipher.doFinal(plaintextBytes)' ;
fid2 = fopen('msg.txt','w');
fwrite(fid2,ciphertext);
fclose(fid2);
I try to decrypt it using:
openssl rsautl -decrypt -inkey private.pem -in msg.txt -keyform PEM -pkcs
Then I get this error:
RSA operation error
80305:error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-59.40.2/src/crypto/rsa/rsa_pk1.c:267:
80305:error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-59.40.2/src/crypto/rsa/rsa_eay.c:614:
Most of the time for such "RSA_padding_check_PKCS1_type_2 error ..." - you tends to see this with
(1) Encoding errors: instead of decrypting binary data, decrypting is done on (maybe) Base64 encoded data.
(2) Mismatched key pair or key itself: Public key does not matched to the Private key for decryption.
http://hustoknow.blogspot.ca/2013/01/rsa-block-type-is-not-02-error.html
Maybe we can make sure the pair is not mismatch (2) too before saying the cipher load is not correct (1). Like below in ref to https://www.sslshopper.com/ssl-converter.html
Convert PEM to DER: openssl x509 -outform der -in certificate.pem -out certificate.der
or if the cert is already in "der" format, can also be turn into "pem"
e.g. Convert DER to PEM: openssl x509 -inform der -in certificate.cer -out certificate.pem
Convert PEM to PFX: openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt
or if there is only "pfx" then can get "pem"
e.g. Convert PFX to PEM: openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes
After making sure we have the "pem", we can try the encrypt and decrypt as stated in
http://openssl.6102.n7.nabble.com/unable-to-decrypt-using-using-private-key-td15204.html
e.g. 1) openssl enc -base64 -d -in -out where was created and it had binary contents.
e.g. 2) openssl rsautl -decrypt -inkey -out -pkcs
but in this case, consider trying to use -raw instead of -pkcs to decrypt data with server private
key

InvalidKeyException when creating PublicKey in Java from openssl ec

I get a InvalidKeyException: invalid key format when creating a java.security.PublicKey from a PEM file generated by openssl ec -pubout ....
The same code works for RSA keys.
What am I doing wrong?
The public key reads:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAG0FCGgyhUeJYUXeXoiKOU4GiyTORZ
U9+OpadxpVWqPbNoSNcfK7Ea13eWOKXlUe22v4Clce3t5nrCEBkwqhhe/g==
-----END PUBLIC KEY-----
EC key generation with OpenSSL:
openssl ecparam -genkey -out private_key.pem -outform PEM -name prime256v1
openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
openssl ec -in private_key.pem -inform PEM -out public_key.pem -outform PEM -pubout
(I already tried different settings for conv_form and param_enc)
Java code:
KeyFactory kf = KeyFactory.getInstance("EC");
byte[] privEncoded = ... // read from private_key.der file
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privEncoded);
PrivateKey privKey = kf.generatePrivate(privSpec);
byte[] pubEncoded = .... // read from public_key.pem file
X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubEncoded);
PublicKey pubKey = kf.generatePublic(pubSpec); // <-- InvalidKeyException
Edit: Contrary to what I said above, reading the RSA public key now fails too when trying it with a newly generated PEM. Also, encrypting and then decrypting fails. Stripping the BEGIN and END line from the PEM and converting Base64 to byte, as suggested by GregS, solved it!
The so-called "PEM" format is not supported by Java. You must either save the data in openssl's "DER" format or strip out the first and last lines and decode the base64 in your Java program. See javax.xml.bind.DataTypeConverter.parseBase64Binary to go from base64 to bytes.

Where can I get a PEM (private) key?

I am working on IdP-initiated SAML response for Salesforce and need your help.
I was working with the code and found that I need a .pem (private) key.
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry("alias", new KeyStore.PasswordProtection(password));
PrivateKey pk = pkEntry.getPrivateKey();
The PEM key will be used to sign my response signature. Where can I get a .pem key?
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj ‘/C=US/ST=CA/L=San Mateo/CN=www.appirio.com’ -keyout key-mycompanyrsa.pem -out cert-mycompanyrsa.pem
More info:
http://blog.jeffdouglas.com/2010/07/06/using-rsa-sha1-with-salesforce-crypto-class/

Categories