Compare PublicKey object in java

2019-02-10 05:13发布

I have two PublicKey object.I want to compare both for equality or to check which is latest object using java security API or bouncy castle API.How can i achieve this?

3条回答
The star\"
2楼-- · 2019-02-10 05:41

Normally public keys are compared using some kind of ID. It depends on the protocol how the key ID is calculated. The best method is probably to keep to the PKCS#11 specifications which defines methods of calculating key ID's.

The creation date is not an integral part of the key itself. Either you have to define it elsewhere, or you should use a public key container such as an X509 certificate. Note that you could use the (hex representation of the) key ID to find the creation date in a map.

It's probably best to use a SHA-1 hash over the modulus as ID. The modulus of both the public key and private key are identical and should be different for each key pair. The following code calculates the ID for an RSA public key.

Obviously you can always directly compare the moduli of two keys as well. Key ID's are a bit easier to store though.

public class CreateRSAPublicKeyID {

    /**
     * Creates a key ID for a given key.
     * 
     * @param key the key
     * @return the key ID for the given key
     */
    public static byte[] createKeyID(Key key) {

        if (key instanceof RSAKey) {
            RSAKey rsaKey = (RSAKey) key;
            BigInteger modulus = rsaKey.getModulus();
            if (modulus.bitLength() % Byte.SIZE != 0) {
                throw new IllegalArgumentException("This method currently only works with RSA key sizes that are a multiple of 8 in bits");
            }
            final byte[] modulusData = i2os(modulus, modulus.bitLength() / Byte.SIZE);
            MessageDigest sha1;
            try {
                sha1 = MessageDigest.getInstance("SHA-1");
            } catch (NoSuchAlgorithmException e) {
                throw new IllegalStateException("SHA-1 message digest should be available in any Java SE runtime", e);
            }
            return sha1.digest(modulusData);
        }

        throw new UnsupportedOperationException("Key type not supported");
    }

    /**
     * Integer to octet string (I2OS) creates a fixed size, left padded, big-endian octet string representation for
     * a given integer.
     * 
     * @param i the integer
     * @param octets the number of octets (bytes)
     * @return the octet string representation of i
     */
    public static byte[] i2os(BigInteger i, int octets) {

        if (i.bitLength() > octets * Byte.SIZE) {
            throw new IllegalArgumentException("i does not fit in " + octets + " octets");
        }

        final byte[] is = i.toByteArray();
        if (is.length == octets) {
            return is;
        }

        final byte[] ius = new byte[octets];
        if (is.length == octets + 1) {
            System.arraycopy(is, 1, ius, 0, octets);
        } else {
            System.arraycopy(is, 0, ius, octets - is.length, is.length);
        }
        return ius;
    }

    public static String toHex(byte[] data) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < data.length; i++) {
            sb.append(String.format("%02X", data[i]));
        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(2048);
        KeyPair pair = kpg.generateKeyPair();
        byte[] keyID = createKeyID(pair.getPublic());
        System.out.println(toHex(keyID));
    }
}

Note that the getModulus() command may not be compatible with some keystores (e.g. those ones that represent HSM tokens or smart cards).

查看更多
啃猪蹄的小仙女
3楼-- · 2019-02-10 05:44

You can use equals

if (!key.equals(copyKey)){
    System.out.println("not equals!");
}

or check the hashcode of the keys

if (key.hashCode() != copyKey.hashCode())
{
    System.out.println("public key hashCode check failed");
}

or compare the hex string of the two public keys

String encodedKey1 = new String(Hex.encode(key1.getEncoded()));
String encodedKey2 = new String(Hex.encode(key2.getEncoded()));

if (!encodedKey1.equals(encodedKey2)){
    System.out.println("not equals!");
}

You have a lot of key comparision and check samples at Bouncy Castle Tests, take a look at the org.bouncycastle.jce.provider.test package for some code. BC is not strictly necesary you can do the comparision with the default java security classes.

查看更多
淡お忘
4楼-- · 2019-02-10 06:06

Lookin at Oracle's documentation, I think you can compare PublicKey using its 3 getters : getAlgorithm, getEncoded, getFormat doing this :

oldKey.getAlgorithm().equals(newKey.getAlgorithm()) and so on.

查看更多
登录 后发表回答