Search code examples
javasslcryptographybouncycastle

How to verify if the private key matches with the certificate..?


I have the private key stored as .key file..

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQD5YBS6V3APdgqaWAkijIUHRK4KQ6eChSaRWaw9L/4u8o3T1s8J
rUFHQhcIo5LPaQ4BrIuzHS8yzZf0m3viCTdZAiDn1ZjC2koquJ53rfDzqYxZFrId
7a4QYUCvM0gqx5nQ+lw1KoY/CDAoZN+sO7IJ4WkMg5XbgTWlSLBeBg0gMwIDAQAB
AoGASKDKCKdUlLwtRFxldLF2QPKouYaQr7u1ytlSB5QFtIih89N5Avl5rJY7/SEe
rdeL48LsAON8DpDAM9Zg0ykZ+/gsYI/C8b5Ch3QVgU9m50j9q8pVT04EOCYmsFi0
DBnwNBRLDESvm1p6NqKEc7zO9zjABgBvwL+loEVa1JFcp5ECQQD9/sekGTzzvKa5
SSVQOZmbwttPBjD44KRKi6LC7rQahM1PDqmCwPFgMVpRZL6dViBzYyWeWxN08Fuv
p+sIwwLrAkEA+1f3VnSgIduzF9McMfZoNIkkZongcDAzjQ8sIHXwwTklkZcCqn69
qTVPmhyEDA/dJeAK3GhalcSqOFRFEC812QJAXStgQCmh2iaRYdYbAdqfJivMFqjG
vgRpP48JHUhCeJfOV/mg5H2yDP8Nil3SLhSxwqHT4sq10Gd6umx2IrimEQJAFNA1
ACjKNeOOkhN+SzjfajJNHFyghEnJiw3NlqaNmEKWNNcvdlTmecObYuSnnqQVqRRD
cfsGPU661c1MpslyCQJBAPqN0VXRMwfU29a3Ve0TF4Aiu1iq88aIPHsT3GKVURpO
XNatMFINBW8ywN5euu8oYaeeKdrVSMW415a5+XEzEBY=
-----END RSA PRIVATE KEY-----

And i extracted public key from ssl certificate file..

Below is the code i tried to verify if private key matches with ssl certificate or not..

I used the modulus[i.e. private key get modulus==public key get modulus] to check if they are matching..

And this seems to hold only for RSAKEYS..

But i want to check for other keys as well..

Is there any other alternative to do the same..??

  private static boolean verifySignature(File serverCertificateFile, File serverCertificateKey) {
    try {
        byte[] certificateBytes = FileUtils.readFileToByteArray(serverCertificateFile);
        //byte[] keyBytes = FileUtils.readFileToByteArray(serverCertificateKey);
        RandomAccessFile raf = new RandomAccessFile(serverCertificateKey, "r");
        byte[] buf = new byte[(int) raf.length()];
        raf.readFully(buf);
        raf.close();
        PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(buf);
        KeyFactory kf;
        try {
            kf = KeyFactory.getInstance("RSA");

            RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(kspec);


            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            InputStream in = new ByteArrayInputStream(certificateBytes);
            //Generate Certificate in X509 Format
            X509Certificate cert = (X509Certificate) certFactory.generateCertificate(in);
            RSAPublicKey publicKey = (RSAPublicKey) cert.getPublicKey();

            in.close();
            return privKey.getModulus() == publicKey.getModulus();

        } catch (NoSuchAlgorithmException ex) {
            logger.log(Level.SEVERE, "Such algorithm is not found", ex);
        }  catch (CertificateException ex) {
            logger.log(Level.SEVERE, "certificate exception", ex);
        } catch (InvalidKeySpecException ex) {
            Logger.getLogger(CertificateConversion.class.getName()).log(Level.SEVERE, null, ex);
        }

    } catch (IOException ex) {
        logger.log(Level.SEVERE, "Signature verification failed.. This could be because the file is in use", ex);
    }
    return false;
}

And the code isn't working either.. throws invalidkeyspec exception


Solution

  • So, what's the problem with pairwise parameter checking?

    • If certificate specifies public key of type “RSA”, then:
      1. Extract n, e from key file.
      2. Compare these values with those in certificate.
    • If certificate specifies public key of type “DSA”, then:
      1. Extract p, q, g, y from key file.
      2. Compare these values with those in certificate.
    • If certificate specifies public key of type “blah-blah”, then:
      1. Extract corresponding values from key file.
      2. Compare these values with those in certificate.

    And so on, i. e. each algorithm requires its own proper handling. No general algorithm may exist, provided that key file format is actually custom. However, you may still slightly generalize it by specifying value indexes only:

    ComparisonScheme = new Dictionary<String, Integer[2][]> {
        { "RSA", {{0, 0}, {1, 1}} },
        { "DSA", {{0, 1}, {1, 2}, {2, 3}, {3, 0}} },
    }
    

    This is just an illustration, of course, — don't get syntax and numbers seriously.