Search in sources :

Example 21 with DSAPrivateKey

use of java.security.interfaces.DSAPrivateKey in project jruby-openssl by jruby.

the class PKeyDSA method initialize.

@JRubyMethod(rest = true, visibility = Visibility.PRIVATE)
public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args) {
    final Ruby runtime = context.runtime;
    if (Arity.checkArgumentCount(runtime, args, 0, 2) == 0) {
        this.privateKey = null;
        this.publicKey = null;
        return this;
    }
    IRubyObject arg = args[0];
    IRubyObject pass = null;
    if (args.length > 1)
        pass = args[1];
    if (arg instanceof RubyFixnum) {
        int keySize = RubyNumeric.fix2int((RubyFixnum) arg);
        return dsaGenerate(context.runtime, this, keySize);
    }
    final char[] passwd = password(pass);
    final RubyString str = readInitArg(context, arg);
    final String strJava = str.toString();
    Object key = null;
    final KeyFactory dsaFactory;
    try {
        dsaFactory = SecurityHelper.getKeyFactory("DSA");
    } catch (NoSuchAlgorithmException e) {
        throw runtime.newRuntimeError("unsupported key algorithm (DSA)");
    } catch (RuntimeException e) {
        throw runtime.newRuntimeError("unsupported key algorithm (DSA) " + e);
    }
    // TODO: ugly NoClassDefFoundError catching for no BC env. How can we remove this?
    boolean noClassDef = false;
    if (key == null && !noClassDef) {
        // PEM_read_bio_DSAPrivateKey
        try {
            key = readPrivateKey(strJava, passwd);
        } catch (NoClassDefFoundError e) {
            noClassDef = true;
            debugStackTrace(runtime, e);
        } catch (PEMInputOutput.PasswordRequiredException retry) {
            if (ttySTDIN(context)) {
                try {
                    key = readPrivateKey(strJava, passwordPrompt(context));
                } catch (Exception e) {
                    debugStackTrace(runtime, e);
                }
            }
        } catch (Exception e) {
            debugStackTrace(runtime, e);
        }
    }
    if (key == null && !noClassDef) {
        // PEM_read_bio_DSAPublicKey
        try {
            key = PEMInputOutput.readDSAPublicKey(new StringReader(strJava), passwd);
        } catch (NoClassDefFoundError e) {
            noClassDef = true;
            debugStackTrace(runtime, e);
        } catch (Exception e) {
            debugStackTrace(runtime, e);
        }
    }
    if (key == null && !noClassDef) {
        // PEM_read_bio_DSA_PUBKEY
        try {
            key = PEMInputOutput.readDSAPubKey(new StringReader(strJava));
        } catch (NoClassDefFoundError e) {
            noClassDef = true;
            debugStackTrace(runtime, e);
        } catch (Exception e) {
            debugStackTrace(runtime, e);
        }
    }
    if (key == null && !noClassDef) {
        // d2i_DSAPrivateKey_bio
        try {
            key = readDSAPrivateKey(dsaFactory, str.getBytes());
        } catch (NoClassDefFoundError e) {
            noClassDef = true;
            debugStackTrace(runtime, e);
        } catch (InvalidKeySpecException e) {
            debug(runtime, "PKeyDSA could not read private key", e);
        } catch (IOException e) {
            debug(runtime, "PKeyDSA could not read private key", e);
        } catch (RuntimeException e) {
            if (isKeyGenerationFailure(e))
                debug(runtime, "PKeyDSA could not read private key", e);
            else
                debugStackTrace(runtime, e);
        }
    }
    if (key == null && !noClassDef) {
        // d2i_DSA_PUBKEY_bio
        try {
            key = readDSAPublicKey(dsaFactory, str.getBytes());
        } catch (NoClassDefFoundError e) {
            noClassDef = true;
            debugStackTrace(runtime, e);
        } catch (InvalidKeySpecException e) {
            debug(runtime, "PKeyDSA could not read public key", e);
        } catch (IOException e) {
            debug(runtime, "PKeyDSA could not read public key", e);
        } catch (RuntimeException e) {
            if (isKeyGenerationFailure(e))
                debug(runtime, "PKeyDSA could not read public key", e);
            else
                debugStackTrace(runtime, e);
        }
    }
    if (key == null)
        key = tryPKCS8EncodedKey(runtime, dsaFactory, str.getBytes());
    if (key == null)
        key = tryX509EncodedKey(runtime, dsaFactory, str.getBytes());
    if (key == null)
        throw newDSAError(runtime, "Neither PUB key nor PRIV key:");
    if (key instanceof KeyPair) {
        final PublicKey pubKey = ((KeyPair) key).getPublic();
        final PrivateKey privKey = ((KeyPair) key).getPrivate();
        if (!(privKey instanceof DSAPrivateKey)) {
            if (privKey == null) {
                throw newDSAError(runtime, "Neither PUB key nor PRIV key: (private key is null)");
            }
            throw newDSAError(runtime, "Neither PUB key nor PRIV key: (invalid key type " + privKey.getClass().getName() + ")");
        }
        this.privateKey = (DSAPrivateKey) privKey;
        this.publicKey = (DSAPublicKey) pubKey;
    } else if (key instanceof DSAPrivateKey) {
        this.privateKey = (DSAPrivateKey) key;
    } else if (key instanceof DSAPublicKey) {
        this.publicKey = (DSAPublicKey) key;
        this.privateKey = null;
    } else {
        throw newDSAError(runtime, "Neither PUB key nor PRIV key: " + key.getClass().getName());
    }
    return this;
}
Also used : PKey.readDSAPrivateKey(org.jruby.ext.openssl.impl.PKey.readDSAPrivateKey) DSAPrivateKey(java.security.interfaces.DSAPrivateKey) PEMInputOutput(org.jruby.ext.openssl.x509store.PEMInputOutput) PKey.readDSAPublicKey(org.jruby.ext.openssl.impl.PKey.readDSAPublicKey) DSAPublicKey(java.security.interfaces.DSAPublicKey) RubyString(org.jruby.RubyString) RubyString(org.jruby.RubyString) IOException(java.io.IOException) IRubyObject(org.jruby.runtime.builtin.IRubyObject) RubyFixnum(org.jruby.RubyFixnum) RaiseException(org.jruby.exceptions.RaiseException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) IOException(java.io.IOException) PKey.readDSAPublicKey(org.jruby.ext.openssl.impl.PKey.readDSAPublicKey) DSAPublicKey(java.security.interfaces.DSAPublicKey) StringReader(java.io.StringReader) PKey.readDSAPrivateKey(org.jruby.ext.openssl.impl.PKey.readDSAPrivateKey) DSAPrivateKey(java.security.interfaces.DSAPrivateKey) IRubyObject(org.jruby.runtime.builtin.IRubyObject) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) Ruby(org.jruby.Ruby) JRubyMethod(org.jruby.anno.JRubyMethod)

Example 22 with DSAPrivateKey

use of java.security.interfaces.DSAPrivateKey in project Zom-Android by zom.

the class OtrCryptoEngineImpl method sign.

public byte[] sign(byte[] b, PrivateKey privatekey) throws OtrCryptoException {
    if (!(privatekey instanceof DSAPrivateKey))
        throw new IllegalArgumentException();
    DSAParams dsaParams = ((DSAPrivateKey) privatekey).getParams();
    DSAParameters bcDSAParameters = new DSAParameters(dsaParams.getP(), dsaParams.getQ(), dsaParams.getG());
    DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) privatekey;
    DSAPrivateKeyParameters bcDSAPrivateKeyParms = new DSAPrivateKeyParameters(dsaPrivateKey.getX(), bcDSAParameters);
    DSASigner dsaSigner = new DSASigner();
    dsaSigner.init(true, bcDSAPrivateKeyParms);
    BigInteger q = dsaParams.getQ();
    // Ian: Note that if you can get the standard DSA implementation you're
    // using to not hash its input, you should be able to pass it ((256-bit
    // value) mod q), (rather than truncating the 256-bit value) and all
    // should be well.
    // ref: Interop problems with libotr - DSA signature
    BigInteger bmpi = new BigInteger(1, b);
    BigInteger[] rs = dsaSigner.generateSignature(BigIntegers.asUnsignedByteArray(bmpi.mod(q)));
    int siglen = q.bitLength() / 4;
    int rslen = siglen / 2;
    byte[] rb = BigIntegers.asUnsignedByteArray(rs[0]);
    byte[] sb = BigIntegers.asUnsignedByteArray(rs[1]);
    // Create the final signature array, padded with zeros if necessary.
    byte[] sig = new byte[siglen];
    Boolean writeR = false;
    Boolean writeS = false;
    int shiftR = rslen - rb.length;
    int shiftS = rslen - sb.length;
    for (int i = 0; i < siglen; i++) {
        if (i < rslen) {
            if (!writeR)
                writeR = rb.length >= rslen - i;
            sig[i] = (writeR) ? rb[i - shiftR] : (byte) 0x0;
        } else {
            // Rebase.
            int j = i - rslen;
            if (!writeS)
                writeS = sb.length >= rslen - j;
            sig[i] = (writeS) ? sb[j - shiftS] : (byte) 0x0;
        }
    }
    return sig;
}
Also used : DSASigner(org.spongycastle.crypto.signers.DSASigner) DSAPrivateKeyParameters(org.spongycastle.crypto.params.DSAPrivateKeyParameters) DSAPrivateKey(java.security.interfaces.DSAPrivateKey) BigInteger(java.math.BigInteger) DSAParams(java.security.interfaces.DSAParams) DSAParameters(org.spongycastle.crypto.params.DSAParameters)

Example 23 with DSAPrivateKey

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

the class DsaTest method testKeyGeneration.

@SuppressWarnings("InsecureCryptoUsage")
public void testKeyGeneration(int keysize) throws Exception {
    KeyPairGenerator generator = KeyPairGenerator.getInstance("DSA");
    generator.initialize(keysize);
    KeyPair keyPair = generator.generateKeyPair();
    DSAPrivateKey priv = (DSAPrivateKey) keyPair.getPrivate();
    DSAParams params = priv.getParams();
    assertEquals(keysize, params.getP().bitLength());
    // The NIST standard does not fully specify the size of q that
    // must be used for a given key size. Hence there are differences.
    // For example if keysize = 2048, then OpenSSL uses 256 bit q's by default,
    // but the SUN provider uses 224 bits. Both are acceptable sizes.
    // The tests below simply asserts that the size of q does not decrease the
    // overall security of the DSA.
    int qsize = params.getQ().bitLength();
    switch(keysize) {
        case 1024:
            assertTrue("Invalid qsize for 1024 bit key:" + qsize, qsize >= 160);
            break;
        case 2048:
            assertTrue("Invalid qsize for 2048 bit key:" + qsize, qsize >= 224);
            break;
        case 3072:
            assertTrue("Invalid qsize for 3072 bit key:" + qsize, qsize >= 256);
            break;
        default:
            fail("Invalid key size:" + keysize);
    }
    // Check the length of the private key.
    // For example GPG4Browsers or the KJUR library derived from it use
    // q.bitCount() instead of q.bitLength() to determine the size of the private key
    // and hence would generate keys that are much too small.
    assertTrue(priv.getX().bitLength() >= qsize - 32);
}
Also used : KeyPair(java.security.KeyPair) DSAPrivateKey(java.security.interfaces.DSAPrivateKey) KeyPairGenerator(java.security.KeyPairGenerator) DSAParams(java.security.interfaces.DSAParams)

Example 24 with DSAPrivateKey

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

the class DsaTest method testTiming.

/**
 * This test checks for potential of a timing attack. The test generates a number of signatures,
 * selects a fraction of them with a small timing and then compares the values k for the selected
 * signatures with a normal distribution. The test fails if these ks are much smaller than
 * expected. An implementation flaw that can lead to a test failure is to compute the signature
 * with a modular exponentiation with a runtime that depend on the length of the exponent.
 *
 * <p>A failing test simply means that the timing can be used to get information about k. Further
 * analysis is necessary to determine if the bias is exploitable and how many timings are
 * necessary for an attack. A passing test does not mean that the implementation is secure against
 * timing attacks. The test only catches relatively big timing differences. It requires high
 * confidence to fail. Noise on the test machine can prevent that a relation between timing and k
 * can be detected.
 *
 * <p>Claims of what is exploitable: http://www.hpl.hp.com/techreports/1999/HPL-1999-90.pdf 30
 * signatures are sufficient to find the private key if the attacker knows 8 bits of each k.
 * http://eprint.iacr.org/2004/277.pdf 27 signatures are sufficient if 8 bits of each k is known.
 * Our own old experiments (using 1GB memory on a Pentium-4? CPU): 2^11 signatures are sufficient
 * with a 3 bit leakage. 2^15 signatures are sufficient with a 2 bit leakage. 2^24 signatures are
 * sufficient with a 1 bit leakage. Estimate for biased generation in the NIST standard: e.g. 2^22
 * signatures, 2^40 memory, 2^64 time
 *
 * <p><b>Sample output for the SUN provider:</b> <code>
 * count:50000 cutoff:4629300 relative average:0.9992225872624547 sigmas:0.3010906585642381
 * count:25000 cutoff:733961 relative average:0.976146066585879 sigmas:6.532668708070148
 * count:12500 cutoff:688305 relative average:0.9070352192339134 sigmas:18.00255238454385
 * count:6251 cutoff:673971 relative average:0.7747148791368986 sigmas:30.850903417893825
 * count:3125 cutoff:667045 relative average:0.5901994097874541 sigmas:39.67877152897901
 * count:1563 cutoff:662088 relative average:0.4060286694971057 sigmas:40.67294313795137
 * count:782 cutoff:657921 relative average:0.2577955312387898 sigmas:35.94906247333319
 * count:391 cutoff:653608 relative average:0.1453438859272699 sigmas:29.271192100879457
 * count:196 cutoff:649280 relative average:0.08035497211567771 sigmas:22.300206785132406
 * count:98 cutoff:645122 relative average:0.05063589092661368 sigmas:16.27820353139225
 * count:49 cutoff:641582 relative average:0.018255560447883384 sigmas:11.903018745467488
 * count:25 cutoff:638235 relative average:0.009082660721102722 sigmas:8.581595888660086
 * count:13 cutoff:633975 relative average:0.0067892346039088326 sigmas:6.20259924188633
 * </code>
 *
 * <p><b>What this shows:</b> The first line uses all 50'000 signatures. The average k of these
 * signatures is close to the expected value q/2. Being more selective gives us signatures with a
 * more biased k. For example, the 196 signatures with the fastest timing have about a 3-bit bias.
 * From this we expect that 2^19 signatures and timings are sufficient to find the private key.
 *
 * <p>A list of problems caught by this test:
 *
 * <ul>
 *   <li>CVE-2016-5548 OpenJDK8's DSA is vulnerable to timing attacks.
 *   <li>CVE-2016-1000341 BouncyCastle before v 1.56 is vulnernerable to timing attacks.
 * </ul>
 */
@SlowTest(providers = { ProviderType.BOUNCY_CASTLE, ProviderType.OPENJDK, ProviderType.SPONGY_CASTLE })
@SuppressWarnings("InsecureCryptoUsage")
@Test
public void testTiming() throws Exception {
    ThreadMXBean bean = ManagementFactory.getThreadMXBean();
    if (!bean.isCurrentThreadCpuTimeSupported()) {
        System.out.println("getCurrentThreadCpuTime is not supported. Skipping");
        return;
    }
    String hashAlgorithm = "SHA-1";
    String message = "Hello";
    byte[] messageBytes = message.getBytes("UTF-8");
    byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes);
    BigInteger h = new BigInteger(1, digest);
    KeyPairGenerator generator = java.security.KeyPairGenerator.getInstance("DSA");
    generator.initialize(1024);
    KeyPair keyPair = generator.generateKeyPair();
    DSAPrivateKey priv = (DSAPrivateKey) keyPair.getPrivate();
    Signature signer = Signature.getInstance("SHA1WITHDSA");
    signer.initSign(priv);
    // The timings below are quite noisy. Thus we need a large number of samples.
    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, false);
    }
    long[] sorted = Arrays.copyOf(timing, timing.length);
    Arrays.sort(sorted);
    // Here we are only interested in roughly the 8 most significant bits of the ks.
    // Hence, using double is sufficiently precise.
    double q = priv.getParams().getQ().doubleValue();
    double expectedAverage = q / 2;
    double maxSigmas = 0;
    System.out.println("testTiming: SHA1WITHDSA");
    for (int idx = samples - 1; idx > 10; idx /= 2) {
        long cutoff = sorted[idx];
        int count = 0;
        double total = 0;
        for (int i = 0; i < samples; i++) {
            if (timing[i] <= cutoff) {
                total += k[i].doubleValue();
                count += 1;
            }
        }
        double expectedStdDev = q / Math.sqrt(12 * count);
        double average = total / count;
        // Number of standard deviations that the average is away from
        // the expected value:
        double sigmas = Math.abs(expectedAverage - average) / expectedStdDev;
        if (sigmas > maxSigmas) {
            maxSigmas = sigmas;
        }
        System.out.println("count:" + count + " cutoff:" + cutoff + " relative average:" + (average / expectedAverage) + " sigmas:" + sigmas);
    }
    // than 10^{-10}.
    if (maxSigmas >= 7) {
        fail("Signatures with short timing have a biased k");
    }
}
Also used : ThreadMXBean(java.lang.management.ThreadMXBean) KeyPair(java.security.KeyPair) KeyPairGenerator(java.security.KeyPairGenerator) Signature(java.security.Signature) BigInteger(java.math.BigInteger) DSAPrivateKey(java.security.interfaces.DSAPrivateKey) SlowTest(com.google.security.wycheproof.WycheproofRunner.SlowTest) SlowTest(com.google.security.wycheproof.WycheproofRunner.SlowTest) Test(org.junit.Test)

Example 25 with DSAPrivateKey

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

the class DsaTest method testBiasSha1WithDSA.

/**
 * Checks whether CVE-2016-0695 has been fixed. Before the April 2016 security update, the SUN
 * provider had a serious flaw that leaked the private key with about 3-5 signatures. In
 * particular, "Sha1WithDSA" always generated 160 bit k's independently of q. Unfortunately, it is
 * easily possible to use 2048 and 3072 bit DSA keys together with SHA1WithDSA. All a user has to
 * do is to use the algorithm name "DSA" instead of "SHA256WithDSA" rsp. "SHA224WithDSA".
 *
 * <p>An algorithm to extract the key from the signatures has been described for example in the
 * paper <a href="http://www.hpl.hp.com/techreports/1999/HPL-1999-90.pdf">Lattice Attacks on
 * Digital Signature Schemes</a> by N.A. Howgrave-Graham, N.P. Smart.
 *
 * <p>This bug is the same as US-CERT: VU # 940388: GnuPG generated ElGamal signatures that leaked
 * the private key.
 */
@SlowTest(providers = { ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE })
@SuppressWarnings("InsecureCryptoUsage")
@Test
public void testBiasSha1WithDSA() throws Exception {
    String hashAlgorithm = "SHA";
    String message = "Hello";
    byte[] messageBytes = message.getBytes("UTF-8");
    byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes);
    BigInteger h = new BigInteger(1, digest);
    KeyPairGenerator generator = java.security.KeyPairGenerator.getInstance("DSA");
    generator.initialize(2048);
    KeyPair keyPair = generator.generateKeyPair();
    DSAPrivateKey priv = (DSAPrivateKey) keyPair.getPrivate();
    Signature signer = Signature.getInstance("DSA");
    try {
        // Private key and selected algorithm by signer do not match.
        // Hence throwing an exception at this point would be the reasonable.
        signer.initSign(priv);
        signer.update(messageBytes);
        byte[] signature = signer.sign();
        BigInteger q = priv.getParams().getQ();
        BigInteger k = extractK(signature, h, priv, true);
        // Now check if k is heavily biased.
        int lengthDiff = q.bitLength() - k.bitLength();
        if (lengthDiff > 32) {
            fail("Severly biased DSA signature:" + " len(q)=" + q.bitLength() + " len(k)=" + k.bitLength());
        }
    } catch (GeneralSecurityException ex) {
        // The key is invalid, hence getting here is reasonable.
        return;
    }
}
Also used : KeyPair(java.security.KeyPair) Signature(java.security.Signature) GeneralSecurityException(java.security.GeneralSecurityException) BigInteger(java.math.BigInteger) DSAPrivateKey(java.security.interfaces.DSAPrivateKey) KeyPairGenerator(java.security.KeyPairGenerator) SlowTest(com.google.security.wycheproof.WycheproofRunner.SlowTest) SlowTest(com.google.security.wycheproof.WycheproofRunner.SlowTest) Test(org.junit.Test)

Aggregations

DSAPrivateKey (java.security.interfaces.DSAPrivateKey)48 BigInteger (java.math.BigInteger)23 DSAParams (java.security.interfaces.DSAParams)18 DSAPublicKey (java.security.interfaces.DSAPublicKey)15 RSAPrivateKey (java.security.interfaces.RSAPrivateKey)14 KeyPair (java.security.KeyPair)12 RSAPrivateCrtKey (java.security.interfaces.RSAPrivateCrtKey)12 DSAPrivateKeySpec (java.security.spec.DSAPrivateKeySpec)11 IOException (java.io.IOException)10 KeyPairGenerator (java.security.KeyPairGenerator)8 DSAPublicKeySpec (java.security.spec.DSAPublicKeySpec)8 InvalidKeyException (java.security.InvalidKeyException)7 ECPrivateKey (java.security.interfaces.ECPrivateKey)7 InvalidKeySpecException (java.security.spec.InvalidKeySpecException)7 Signature (java.security.Signature)6 PKCS8EncodedKeySpec (java.security.spec.PKCS8EncodedKeySpec)6 X509EncodedKeySpec (java.security.spec.X509EncodedKeySpec)6 PrivateKey (java.security.PrivateKey)5 SlowTest (com.google.security.wycheproof.WycheproofRunner.SlowTest)4 Test (org.junit.Test)4