Showing posts with label X509Certificate. Show all posts
Showing posts with label X509Certificate. Show all posts

Wednesday, May 24, 2017

How to sign string as well sign request body with public key using Java

Below is a code snippet which will sign your request using Public key.


package com.pkm.src;

import Base64OutputStream;
import IOUtil;

import javax.crypto.Cipher;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.security.MessageDigest;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

/**
 * Created by pritom on 24/05/2017.
 */
public class SignatureSigner {
    public static void main(String[] args) throws Exception {
        String certificateFile = ".....\\publickey.cer";
        String requestBody = "Param1=Value_Of_Param1&Param2=Value_Of_param2";
        String signature = encodeRSASHA1(certificateFile, requestBody);
        System.out.println("Signature=" + signature);
    }

    protected static String encodeRSASHA1(String certificateFile, String requestBody) throws Exception {
        FileInputStream certIn1 = new FileInputStream(certificateFile);
        CertificateFactory e = CertificateFactory.getInstance("X509");
        X509Certificate myCertificate = (X509Certificate) e.generateCertificate(certIn1);

        MessageDigest hashGen = MessageDigest.getInstance("SHA1");
        byte[] hash = hashGen.digest(requestBody.getBytes("UTF-8"));
        Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        rsa.init(1, myCertificate);
        byte[] signature = rsa.doFinal(hash);

        ByteArrayInputStream sigIn = new ByteArrayInputStream(signature);
        ByteArrayOutputStream sigOut = new ByteArrayOutputStream();
        Base64OutputStream base64Out = new Base64OutputStream(sigOut, "");
        IOUtil.copy(sigIn, base64Out);
        base64Out.close();
        return new String(sigOut.toByteArray(), "US-ASCII");
    }
}

Which will output as below:

Signature=7GNccit4cY+rs4t/S0WBv.........+w1rYdiEO8PxuR3SQ=

Wednesday, May 27, 2015

javax.net.ssl.SSLException: Received fatal alert: unexpected_message

This seems like a protocol version mismatch, this exception normally happens when there is a mismatch between SSL protocol version used by the client and the server. your clients should use a protocol version supported by the server.

You could probably enable the SSLv2 protocol at the JVM but that is  is a serious security risk. The clients are using an outdated and insecure protocol and should be updated to TLSv1.1 or TLSv.1.2.

Below is nice solution to resolve the error javax.net.ssl.SSLException: Received fatal alert: unexpected_message.


System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2,SSLv3,SSLv2Hello");

OR

System.setProperty("com.sun.net.ssl.enableECC","false");
System.setProperty("jsse.enableSNIExtension","false");

AND

import javax.net.ssl.*
import java.security.SecureRandom
import java.security.cert.CertificateException
import java.security.cert.X509Certificate;

HttpsURLConnection connection = (HttpsURLConnection) new URL(requestURL).openConnection();
setAcceptAllVerifier(connection);

private static SSLSocketFactory sslSocketFactory = null;

private static void setAcceptAllVerifier(HttpsURLConnection connection) throws Exception {
    if (sslSocketFactory == null) {
        TrustManager trustManager = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        SSLContext sslContext = SSLContext.getInstance("SSLv3");
        sslContext.init(null, trustManager as TrustManager[], new SecureRandom());
        sslSocketFactory = sslContext.getSocketFactory();
    }
    connection.setSSLSocketFactory(sslSocketFactory);
    connection.setHostnameVerifier(ALL_TRUSTING_HOSTNAME_VERIFIER);
}

private static final HostnameVerifier ALL_TRUSTING_HOSTNAME_VERIFIER = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};