How to verify if the private key matches with the certificate..?
Solution 1
So, what's the problem with pairwise parameter checking?
- If certificate specifies public key of type “RSA”, then:
- Extract
n
,e
from key file. - Compare these values with those in certificate.
- Extract
- If certificate specifies public key of type “DSA”, then:
- Extract
p
,q
,g
,y
from key file. - Compare these values with those in certificate.
- Extract
- If certificate specifies public key of type “blah-blah”, then:
- Extract corresponding values from key file.
- 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.
Solution 2
Sign something with the private key and verify it with the public key from the certificate. This will fail unless they are a pair.
Solution 3
If you want to check, if a RSA publicKey and a RSA privateKey belong together, you can use the following code:
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
return rsaPublicKey.getModulus().equals( rsaPrivateKey.getModulus() )
&& BigInteger.valueOf( 2 ).modPow( rsaPublicKey.getPublicExponent()
.multiply( rsaPrivateKey.getPrivateExponent() ).subtract( BigInteger.ONE ),
rsaPublicKey.getModulus() ).equals( BigInteger.ONE );
I am searching for a similar solution for EC...
By now we already found a way for ECC: It is however a little more complicated:
ECPublicKey pk = (ECPublicKey) publicKey;
ECPrivateKey sk = (ECPrivateKey) privateKey;
ECParameterSpec pkSpec = pk.getParams(), skSpec = sk.getParams();
EllipticCurve skCurve = skSpec.getCurve(), pkCurve = pkSpec.getCurve();
ECField skField = skCurve.getField(), pkField = pkCurve.getField();
BigInteger skA = skCurve.getA(), skB = skCurve.getB();
if ( pkSpec != skSpec //
&& ( pkSpec.getCofactor() != skSpec.getCofactor() //
|| ! pkSpec.getOrder().equals( skSpec.getOrder() ) //
|| ! pkSpec.getGenerator().equals( skSpec.getGenerator() ) //
|| pkCurve != skCurve //
&& ( ! pkCurve.getA().equals( skA ) //
|| ! pkCurve.getB().equals( skB ) //
|| skField.getFieldSize() != pkField.getFieldSize() ) ) ) //
return false;
ECPoint w = pk.getW();
BigInteger x = w.getAffineX(), y = w.getAffineY();
if ( skField instanceof ECFieldFp ) {
BigInteger skP = ( (ECFieldFp) skField ).getP();
return pkField instanceof ECFieldFp && skP.equals( ( (ECFieldFp) pkField ).getP() ) //
&& y.pow( 2 ).subtract( x.pow( 3 ) ).subtract( skA.multiply( x ) ).subtract( skB ).mod( skP ).signum() == 0;
}
if ( skField instanceof ECFieldF2m ) {
int m = ( (ECFieldF2m) skField ).getM();
BigInteger rp = ( (ECFieldF2m) skField ).getReductionPolynomial();
if ( ! ( pkField instanceof ECFieldF2m ) || m != ( (ECFieldF2m) skField ).getM() || ! rp.equals( ( (ECFieldF2m) skField ).getReductionPolynomial() ) )
return false;
BigInteger x2 = f2mReduce( f2mMultiply( x, x ), rp, m );
return f2mReduce( f2mSum( f2mMultiply( y, y ), f2mMultiply( x, y ), f2mMultiply( x, x2 ), f2mMultiply( skA, x2 ), skB ), rp, m ).signum() == 0;
}
And here are the math helper function:
public static final BigInteger f2mSum( BigInteger ... values )
{
if ( values.length == 0 )
return BigInteger.ZERO;
BigInteger result = values[ 0 ];
for ( int i = values.length - 1; i > 0; i -- )
result = result.xor( values[ i ] );
return result;
}
public static final BigInteger f2mAdd( BigInteger a, BigInteger b )
{
return a.xor( b );
}
public static final BigInteger f2mSubtract( BigInteger a, BigInteger b )
{
return a.xor( b );
}
public static final BigInteger f2mMultiply( BigInteger a, BigInteger b )
{
BigInteger result = BigInteger.ZERO, sparse, full;
if ( a.bitCount() > b.bitCount() ) {
sparse = b;
full = a;
} else {
sparse = b;
full = a;
}
for ( int i = sparse.bitLength(); i >= 0; i -- )
if ( sparse.testBit( i ) )
result = result.xor( full.shiftLeft( i ) );
return result;
}
public static final BigInteger f2mReduce( BigInteger input, BigInteger reductionPolynom, int bitLength )
{
while ( input.bitLength() > bitLength )
input = input.xor( reductionPolynom.shiftLeft( input.bitLength() - reductionPolynom.bitLength() ) );
return input;
}
Solution 4
Your code is fine, just add the following:
String file = "qwerty";
byte[] fileBytes = file.getBytes();
byte[] digitalSignature = signData(fileBytes, privKey);
System.out.println("SIGNATURE MADE");
boolean verified;
verified = verifySig(fileBytes, publicKey, digitalSignature);
System.out.println("verified: " + verified) ;
public static byte[] signData(byte[] data, PrivateKey key) throws Exception {
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(key);
signer.update(data);
return (signer.sign());
}
public static boolean verifySig(byte[] data, PublicKey key, byte[] sig) throws Exception {
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initVerify(key);
signer.update(data);
return (signer.verify(sig));
}
surendhar_s
Updated on June 04, 2022Comments
-
surendhar_s almost 2 years
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
-
Vadzim over 6 yearsDid you find the solution for EC by now?
-
user207421 over 6 yearsThat's just a coding problem. It has nothing to do with this answer.
-
deFreitas over 6 yearsjava.lang.ClassCastException: sun.security.rsa.RSAPrivateKeyImpl cannot be cast to java.security.interfaces.ECKey
-
Vadzim over 6 years@deFreitas, refer to other answers on RSA case. This one only complements them on EC case.
-
Steffen Heil over 6 yearsSigning something and checking the result is like validating a mathematical formula by testing if it holds for one certain variable assignment. It's better to check the properties of the parameters against the algorithm requirement. As an example, see my answer for code for RSA and ECC. DSA is as easy as RSA.
-
Vadzim over 6 yearsThanks for the EC case, Steffen. But I've noticed that
f2mAdd
andf2mSubtract
are unused andf2mMultiply
has identical branches forif ( a.bitCount() > b.bitCount() )
which seems to be a mistake. Could you, please, also reference the source of the algorythm? -
Bassam over 5 yearsIf you're worried about getting lucky with one test. Run the test against different values. If it checks out, the keys very highly likely make a pair.
-
Bassam over 5 years@user207421 this would work only if the algorithm is supported by a provider in Java.
-
user207421 over 5 years@SteffenHeil It only has to hold for one certain variable. The private key only has one value.