Search in sources :

Example 6 with ECPrivateKey

use of java.security.interfaces.ECPrivateKey in project wycheproof by google.

the class EcdsaTest method testBias.

/** Checks whether the one time key k in ECDSA is biased. */
public void testBias(String algorithm, String curve, ECParameterSpec ecParams) throws Exception {
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
    try {
        keyGen.initialize(ecParams);
    } catch (InvalidAlgorithmParameterException ex) {
        System.out.println("This provider does not support curve:" + curve);
        return;
    }
    KeyPair keyPair = keyGen.generateKeyPair();
    ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
    // If we throw a fair coin tests times then the probability that
    // either heads or tails appears less than mincount is less than 2^{-32}.
    // Therefore the test below is not expected to fail unless the generation
    // of the one time keys is indeed biased.
    final int tests = 1024;
    final int mincount = 410;
    String hashAlgorithm = getHashAlgorithm(algorithm);
    String message = "Hello";
    byte[] messageBytes = message.getBytes("UTF-8");
    byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes);
    // TODO(bleichen): Truncate the digest if the digest size is larger than the
    //   curve size.
    BigInteger h = new BigInteger(1, digest);
    BigInteger q = priv.getParams().getOrder();
    BigInteger qHalf = q.shiftRight(1);
    Signature signer = Signature.getInstance(algorithm);
    signer.initSign(priv);
    // count the number of k's with msb set
    int countLsb = 0;
    // count the number of k's with lsb set
    int countMsb = 0;
    for (int i = 0; i < tests; i++) {
        signer.update(messageBytes);
        byte[] signature = signer.sign();
        BigInteger k = extractK(signature, h, priv);
        if (k.testBit(0)) {
            countLsb++;
        }
        if (k.compareTo(qHalf) == 1) {
            countMsb++;
        }
    }
    System.out.println(signer.getProvider().getName() + " curve:" + curve + " countLsb:" + countLsb + " countMsb:" + countMsb);
    if (countLsb < mincount || countLsb > tests - mincount) {
        fail("Bias detected in the least significant bit of k:" + countLsb);
    }
    if (countMsb < mincount || countMsb > tests - mincount) {
        fail("Bias detected in the most significant bit of k:" + countMsb);
    }
}
Also used : ECPrivateKey(java.security.interfaces.ECPrivateKey) KeyPair(java.security.KeyPair) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) Signature(java.security.Signature) BigInteger(java.math.BigInteger) KeyPairGenerator(java.security.KeyPairGenerator) ECPoint(java.security.spec.ECPoint)

Example 7 with ECPrivateKey

use of java.security.interfaces.ECPrivateKey in project wycheproof by google.

the class EcKeyTest method testKeyGeneration.

/**
   * Tests key generation for given parameters. The test can be skipped if the curve is not a
   * standard curve.
   */
void testKeyGeneration(ECParameterSpec ecParams, boolean isStandard) throws Exception {
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
    KeyPair keyPair;
    try {
        keyGen.initialize(ecParams);
        keyPair = keyGen.generateKeyPair();
    } catch (InvalidAlgorithmParameterException ex) {
        if (!isStandard) {
            return;
        }
        throw ex;
    }
    ECPublicKey pub = (ECPublicKey) keyPair.getPublic();
    ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
    EcUtil.checkPublicKey(pub);
    BigInteger s = priv.getS();
    // Check the length of s. Could fail with probability 2^{-32}.
    assertTrue(s.bitLength() >= EcUtil.fieldSizeInBits(ecParams.getCurve()) - 32);
// TODO(bleichen): correct curve?
// TODO(bleichen): use RandomUtil
}
Also used : ECPrivateKey(java.security.interfaces.ECPrivateKey) KeyPair(java.security.KeyPair) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) ECPublicKey(java.security.interfaces.ECPublicKey) BigInteger(java.math.BigInteger) KeyPairGenerator(java.security.KeyPairGenerator)

Example 8 with ECPrivateKey

use of java.security.interfaces.ECPrivateKey in project wycheproof by google.

the class EcdhTest method testModifiedPublicSpec.

/**
   * This is a similar test as testModifiedPublic. However, this test uses test vectors
   * ECPublicKeySpec
   */
@SuppressWarnings("InsecureCryptoUsage")
public void testModifiedPublicSpec(String algorithm) throws Exception {
    KeyAgreement ka;
    try {
        ka = KeyAgreement.getInstance(algorithm);
    } catch (NoSuchAlgorithmException ex) {
        System.out.println("testWrongOrder: " + algorithm + " not supported");
        return;
    }
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
    keyGen.initialize(EcUtil.getNistP256Params());
    ECPrivateKey priv = (ECPrivateKey) keyGen.generateKeyPair().getPrivate();
    KeyFactory kf = KeyFactory.getInstance("EC");
    ECPublicKey validKey = (ECPublicKey) kf.generatePublic(EC_VALID_PUBLIC_KEY.getSpec());
    ka.init(priv);
    ka.doPhase(validKey, true);
    String expected = TestUtil.bytesToHex(ka.generateSecret());
    for (EcPublicKeyTestVector test : EC_MODIFIED_PUBLIC_KEYS) {
        ECPublicKeySpec spec = test.getSpec();
        if (spec == null) {
            // spec == null if one of these validity checks fails. Of course such a failure is OK.
            continue;
        }
        try {
            ECPublicKey modifiedKey = (ECPublicKey) kf.generatePublic(spec);
            ka.init(priv);
            ka.doPhase(modifiedKey, true);
            String shared = TestUtil.bytesToHex(ka.generateSecret());
            // The implementation did not notice that the public key was modified.
            // This is not nice, but at the moment we only fail the test if the
            // modification was essential for computing the shared secret.
            //
            // BouncyCastle v.1.53 fails this test, for ECDHC with modified order.
            // This implementation reduces the product s*h modulo the order given
            // in the public key. An attacker who can modify the order of the public key
            // and who can learn whether such a modification changes the shared secret is
            // able to learn the private key with a simple binary search.
            assertEquals("algorithm:" + algorithm + " test:" + test.comment, expected, shared);
        } catch (GeneralSecurityException ex) {
            // OK, since the public keys have been modified.
            System.out.println("testModifiedPublic:" + test.comment + " throws " + ex.toString());
        }
    }
}
Also used : ECPrivateKey(java.security.interfaces.ECPrivateKey) ECPublicKey(java.security.interfaces.ECPublicKey) GeneralSecurityException(java.security.GeneralSecurityException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) KeyPairGenerator(java.security.KeyPairGenerator) KeyAgreement(javax.crypto.KeyAgreement) KeyFactory(java.security.KeyFactory) ECPublicKeySpec(java.security.spec.ECPublicKeySpec)

Example 9 with ECPrivateKey

use of java.security.interfaces.ECPrivateKey in project wycheproof by google.

the class EcdhTest method testModifiedPublic.

/**
   * This test modifies the order of group in the public key. A severe bug would be an
   * implementation that leaks information whether the private key is larger than the order given in
   * the public key. Also a severe bug would be to reduce the private key modulo the order given in
   * the public key parameters.
   */
@SuppressWarnings("InsecureCryptoUsage")
public void testModifiedPublic(String algorithm) throws Exception {
    KeyAgreement ka;
    try {
        ka = KeyAgreement.getInstance(algorithm);
    } catch (NoSuchAlgorithmException ex) {
        System.out.println("testWrongOrder: " + algorithm + " not supported");
        return;
    }
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
    keyGen.initialize(EcUtil.getNistP256Params());
    ECPrivateKey priv = (ECPrivateKey) keyGen.generateKeyPair().getPrivate();
    KeyFactory kf = KeyFactory.getInstance("EC");
    ECPublicKey validKey = (ECPublicKey) kf.generatePublic(EC_VALID_PUBLIC_KEY.getSpec());
    ka.init(priv);
    ka.doPhase(validKey, true);
    String expected = TestUtil.bytesToHex(ka.generateSecret());
    for (EcPublicKeyTestVector test : EC_MODIFIED_PUBLIC_KEYS) {
        try {
            X509EncodedKeySpec spec = test.getX509EncodedKeySpec();
            ECPublicKey modifiedKey = (ECPublicKey) kf.generatePublic(spec);
            ka.init(priv);
            ka.doPhase(modifiedKey, true);
            String shared = TestUtil.bytesToHex(ka.generateSecret());
            // The implementation did not notice that the public key was modified.
            // This is not nice, but at the moment we only fail the test if the
            // modification was essential for computing the shared secret.
            //
            // BouncyCastle v.1.53 fails this test, for ECDHC with modified order.
            // This implementation reduces the product s*h modulo the order given
            // in the public key. An attacker who can modify the order of the public key
            // and who can learn whether such a modification changes the shared secret is
            // able to learn the private key with a simple binary search.
            assertEquals("algorithm:" + algorithm + " test:" + test.comment, expected, shared);
        } catch (GeneralSecurityException ex) {
            // OK, since the public keys have been modified.
            System.out.println("testModifiedPublic:" + test.comment + " throws " + ex.toString());
        }
    }
}
Also used : ECPrivateKey(java.security.interfaces.ECPrivateKey) ECPublicKey(java.security.interfaces.ECPublicKey) GeneralSecurityException(java.security.GeneralSecurityException) X509EncodedKeySpec(java.security.spec.X509EncodedKeySpec) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) KeyPairGenerator(java.security.KeyPairGenerator) KeyAgreement(javax.crypto.KeyAgreement) KeyFactory(java.security.KeyFactory)

Example 10 with ECPrivateKey

use of java.security.interfaces.ECPrivateKey in project wycheproof by google.

the class EcdsaTest method testTiming.

/**
   * Tests for a potential timing attack. This test checks if there is a correlation between the
   * timing of signature generation and the size of the one-time key k. This is for example the case
   * if a double and add method is used for the point multiplication. The test fails if such a
   * correlation can be shown with high confidence. Further analysis will be necessary to determine
   * how easy it is to exploit the bias in a timing attack.
   */
// TODO(bleichen): Determine if there are exploitable providers.
//
// SunEC currently fails this test. Since ECDSA typically is used with EC groups whose order
// is 224 bits or larger, it is unclear whether the same attacks that apply to DSA are practical.
//
// The ECDSA implementation in BouncyCastle leaks information about k through timing too.
// The test has not been optimized to detect this bias. It would require about 5'000'000 samples,
// which is too much for a simple unit test.
//
// BouncyCastle uses FixedPointCombMultiplier for ECDSA. This is a method using
// precomputation. The implementation is not constant time, since the precomputation table
// contains the point at infinity and adding this point is faster than ordinary point additions.
// The timing leak only has a small correlation to the size of k and at the moment it is is very
// unclear if the can be exploited. (Randomizing the precomputation table by adding the same
// random point to each element in the table and precomputing the necessary offset to undo the
// precomputation seems much easier than analyzing this.)
public void testTiming(String algorithm, String curve, ECParameterSpec ecParams) throws Exception {
    ThreadMXBean bean = ManagementFactory.getThreadMXBean();
    if (!bean.isCurrentThreadCpuTimeSupported()) {
        System.out.println("getCurrentThreadCpuTime is not supported. Skipping");
        return;
    }
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
    try {
        keyGen.initialize(ecParams);
    } catch (InvalidAlgorithmParameterException ex) {
        System.out.println("This provider does not support curve:" + curve);
        return;
    }
    KeyPair keyPair = keyGen.generateKeyPair();
    ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
    String message = "Hello";
    String hashAlgorithm = getHashAlgorithm(algorithm);
    byte[] messageBytes = message.getBytes("UTF-8");
    byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes);
    BigInteger h = new BigInteger(1, digest);
    Signature signer = Signature.getInstance(algorithm);
    signer.initSign(priv);
    // The number of samples used for the test. This number is a bit low.
    // I.e. it just barely detects that SunEC leaks information about the size of k.
    int samples = 50000;
    long[] timing = new long[samples];
    BigInteger[] k = new BigInteger[samples];
    for (int i = 0; i < samples; i++) {
        long start = bean.getCurrentThreadCpuTime();
        signer.update(messageBytes);
        byte[] signature = signer.sign();
        timing[i] = bean.getCurrentThreadCpuTime() - start;
        k[i] = extractK(signature, h, priv);
    }
    long[] sorted = Arrays.copyOf(timing, timing.length);
    Arrays.sort(sorted);
    double n = priv.getParams().getOrder().doubleValue();
    double expectedAverage = n / 2;
    double maxSigma = 0;
    System.out.println("testTiming algorithm:" + algorithm);
    for (int idx = samples - 1; idx > 10; idx /= 2) {
        long cutoff = sorted[idx];
        int count = 0;
        BigInteger total = BigInteger.ZERO;
        for (int i = 0; i < samples; i++) {
            if (timing[i] <= cutoff) {
                total = total.add(k[i]);
                count += 1;
            }
        }
        double expectedStdDev = n / Math.sqrt(12 * count);
        double average = total.doubleValue() / count;
        // Number of standard deviations that the average is away from
        // the expected value:
        double sigmas = (expectedAverage - average) / expectedStdDev;
        if (sigmas > maxSigma) {
            maxSigma = sigmas;
        }
        System.out.println("count:" + count + " cutoff:" + cutoff + " relative average:" + (average / expectedAverage) + " sigmas:" + sigmas);
    }
    // than 10^{-10}.
    if (maxSigma >= 7) {
        fail("Signatures with short timing have a biased k");
    }
}
Also used : ThreadMXBean(java.lang.management.ThreadMXBean) ECPrivateKey(java.security.interfaces.ECPrivateKey) KeyPair(java.security.KeyPair) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) KeyPairGenerator(java.security.KeyPairGenerator) ECPoint(java.security.spec.ECPoint) Signature(java.security.Signature) BigInteger(java.math.BigInteger)

Aggregations

ECPrivateKey (java.security.interfaces.ECPrivateKey)16 KeyPairGenerator (java.security.KeyPairGenerator)9 ECPublicKey (java.security.interfaces.ECPublicKey)8 KeyFactory (java.security.KeyFactory)6 KeyPair (java.security.KeyPair)6 BigInteger (java.math.BigInteger)5 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)4 Signature (java.security.Signature)4 ECParameterSpec (java.security.spec.ECParameterSpec)4 ECPoint (java.security.spec.ECPoint)4 PKCS8EncodedKeySpec (java.security.spec.PKCS8EncodedKeySpec)4 GeneralSecurityException (java.security.GeneralSecurityException)3 InvalidAlgorithmParameterException (java.security.InvalidAlgorithmParameterException)3 DSAPrivateKey (java.security.interfaces.DSAPrivateKey)3 ECPublicKeySpec (java.security.spec.ECPublicKeySpec)3 X509EncodedKeySpec (java.security.spec.X509EncodedKeySpec)3 KeyAgreement (javax.crypto.KeyAgreement)3 InvalidKeyException (java.security.InvalidKeyException)2 PrivateKey (java.security.PrivateKey)2 Provider (java.security.Provider)2