package org.apache.harmony.xnet.provider.jsse; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Implements the JDK MessageDigest interface using OpenSSL's EVP API. */ public class OpenSSLMessageDigestJDK extends MessageDigest { /** * Holds a pointer to the native message digest context. */ private int ctx; /** * Holds a dummy buffer for writing single bytes to the digest. */ private byte[] singleByte = new byte[1]; /** * Creates a new OpenSSLMessageDigestJDK instance for the given algorithm * name. * * @param algorithm The name of the algorithm, e.g. "SHA1". * * @return The new OpenSSLMessageDigestJDK instance. * * @throws RuntimeException In case of problems. */ public static OpenSSLMessageDigestJDK getInstance(String algorithm) throws NoSuchAlgorithmException{ return new OpenSSLMessageDigestJDK(algorithm); } /** * Creates a new OpenSSLMessageDigest instance for the given algorithm * name. * * @param algorithm The name of the algorithm, e.g. "SHA1". */ private OpenSSLMessageDigestJDK(String algorithm) throws NoSuchAlgorithmException { super(algorithm); // We don't support MD2 anymore. This needs to also check for aliases // and OIDs. if ("MD2".equalsIgnoreCase(algorithm) || "1.2.840.113549.2.2" .equalsIgnoreCase(algorithm)) { throw new NoSuchAlgorithmException(algorithm); } ctx = NativeCrypto.EVP_new(); try { NativeCrypto.EVP_DigestInit(ctx, getAlgorithm().replace("-", "").toLowerCase()); } catch (Exception ex) { throw new NoSuchAlgorithmException(ex.getMessage() + " (" + algorithm + ")"); } } @Override protected byte[] engineDigest() { byte[] result = new byte[NativeCrypto.EVP_DigestSize(ctx)]; NativeCrypto.EVP_DigestFinal(ctx, result, 0); engineReset(); return result; } @Override protected void engineReset() { NativeCrypto.EVP_DigestInit(ctx, getAlgorithm().replace("-", "").toLowerCase()); } @Override protected int engineGetDigestLength() { return NativeCrypto.EVP_DigestSize(ctx); } @Override protected void engineUpdate(byte input) { singleByte[0] = input; engineUpdate(singleByte, 0, 1); } @Override protected void engineUpdate(byte[] input, int offset, int len) { NativeCrypto.EVP_DigestUpdate(ctx, input, offset, len); } @Override protected void finalize() throws Throwable { super.finalize(); NativeCrypto.EVP_free(ctx); } static public class MD5 extends OpenSSLMessageDigestJDK { public MD5() throws NoSuchAlgorithmException { super("MD5"); } } static public class SHA1 extends OpenSSLMessageDigestJDK { public SHA1() throws NoSuchAlgorithmException { super("SHA-1"); } } static public class SHA224 extends OpenSSLMessageDigestJDK { public SHA224() throws NoSuchAlgorithmException { super("SHA-224"); } } static public class SHA256 extends OpenSSLMessageDigestJDK { public SHA256() throws NoSuchAlgorithmException { super("SHA-256"); } } }