src/net/java/otr4j/crypto/OtrCryptoEngineImpl.java
changeset 1040 197a85a35cba
parent 1039 7d6f2526244a
child 1041 e5a970600066
--- a/src/net/java/otr4j/crypto/OtrCryptoEngineImpl.java	Sun Mar 15 17:28:04 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.crypto;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.interfaces.DSAParams;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-
-import javax.crypto.KeyAgreement;
-import javax.crypto.interfaces.DHPrivateKey;
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.DHPrivateKeySpec;
-import javax.crypto.spec.DHPublicKeySpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import net.java.otr4j.io.SerializationUtils;
-
-import org.bouncycastle2.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle2.crypto.BufferedBlockCipher;
-import org.bouncycastle2.crypto.engines.AESFastEngine;
-import org.bouncycastle2.crypto.generators.DHKeyPairGenerator;
-import org.bouncycastle2.crypto.modes.SICBlockCipher;
-import org.bouncycastle2.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle2.crypto.params.DHParameters;
-import org.bouncycastle2.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle2.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle2.crypto.params.DSAParameters;
-import org.bouncycastle2.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle2.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle2.crypto.params.KeyParameter;
-import org.bouncycastle2.crypto.params.ParametersWithIV;
-import org.bouncycastle2.crypto.signers.DSASigner;
-import org.bouncycastle2.util.BigIntegers;
-
-/**
- * 
- * @author George Politis
- * 
- */
-public class OtrCryptoEngineImpl implements OtrCryptoEngine {
-
-	public KeyPair generateDHKeyPair() throws OtrCryptoException {
-
-		// Generate a AsymmetricCipherKeyPair using BC.
-		DHParameters dhParams = new DHParameters(MODULUS, GENERATOR, null,
-				DH_PRIVATE_KEY_MINIMUM_BIT_LENGTH);
-		DHKeyGenerationParameters params = new DHKeyGenerationParameters(
-				new SecureRandom(), dhParams);
-		DHKeyPairGenerator kpGen = new DHKeyPairGenerator();
-
-		kpGen.init(params);
-		AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
-		// Convert this AsymmetricCipherKeyPair to a standard JCE KeyPair.
-		DHPublicKeyParameters pub = (DHPublicKeyParameters) pair.getPublic();
-		DHPrivateKeyParameters priv = (DHPrivateKeyParameters) pair
-				.getPrivate();
-
-		try {
-			KeyFactory keyFac = KeyFactory.getInstance("DH");
-
-			DHPublicKeySpec pubKeySpecs = new DHPublicKeySpec(pub.getY(),
-					MODULUS, GENERATOR);
-			DHPublicKey pubKey = (DHPublicKey) keyFac
-					.generatePublic(pubKeySpecs);
-
-			DHParameters dhParameters = priv.getParameters();
-			DHPrivateKeySpec privKeySpecs = new DHPrivateKeySpec(priv.getX(),
-					dhParameters.getP(), dhParameters.getG());
-			DHPrivateKey privKey = (DHPrivateKey) keyFac
-					.generatePrivate(privKeySpecs);
-
-			return new KeyPair(pubKey, privKey);
-		} catch (Exception e) {
-			throw new OtrCryptoException(e);
-		}
-	}
-
-	public DHPublicKey getDHPublicKey(byte[] mpiBytes)
-			throws OtrCryptoException {
-		return getDHPublicKey(new BigInteger(mpiBytes));
-	}
-
-	public DHPublicKey getDHPublicKey(BigInteger mpi) throws OtrCryptoException {
-		DHPublicKeySpec pubKeySpecs = new DHPublicKeySpec(mpi, MODULUS,
-				GENERATOR);
-		try {
-			KeyFactory keyFac = KeyFactory.getInstance("DH");
-			return (DHPublicKey) keyFac.generatePublic(pubKeySpecs);
-		} catch (Exception e) {
-			throw new OtrCryptoException(e);
-		}
-	}
-
-	public byte[] sha256Hmac(byte[] b, byte[] key) throws OtrCryptoException {
-		return this.sha256Hmac(b, key, 0);
-	}
-
-	public byte[] sha256Hmac(byte[] b, byte[] key, int length)
-			throws OtrCryptoException {
-
-		SecretKeySpec keyspec = new SecretKeySpec(key, "HmacSHA256");
-		javax.crypto.Mac mac;
-		try {
-			mac = javax.crypto.Mac.getInstance("HmacSHA256");
-		} catch (NoSuchAlgorithmException e) {
-			throw new OtrCryptoException(e);
-		}
-		try {
-			mac.init(keyspec);
-		} catch (InvalidKeyException e) {
-			throw new OtrCryptoException(e);
-		}
-
-		byte[] macBytes = mac.doFinal(b);
-
-		if (length > 0) {
-			byte[] bytes = new byte[length];
-			ByteBuffer buff = ByteBuffer.wrap(macBytes);
-			buff.get(bytes);
-			return bytes;
-		} else {
-			return macBytes;
-		}
-	}
-
-	public byte[] sha1Hmac(byte[] b, byte[] key, int length)
-			throws OtrCryptoException {
-
-		try {
-			SecretKeySpec keyspec = new SecretKeySpec(key, "HmacSHA1");
-			javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
-			mac.init(keyspec);
-
-			byte[] macBytes = mac.doFinal(b);
-
-			if (length > 0) {
-				byte[] bytes = new byte[length];
-				ByteBuffer buff = ByteBuffer.wrap(macBytes);
-				buff.get(bytes);
-				return bytes;
-			} else {
-				return macBytes;
-			}
-		} catch (Exception e) {
-			throw new OtrCryptoException(e);
-		}
-	}
-
-	public byte[] sha256Hmac160(byte[] b, byte[] key) throws OtrCryptoException {
-		return sha256Hmac(b, key, 20);
-	}
-
-	public byte[] sha256Hash(byte[] b) throws OtrCryptoException {
-		try {
-			MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
-			sha256.update(b, 0, b.length);
-			return sha256.digest();
-		} catch (Exception e) {
-			throw new OtrCryptoException(e);
-		}
-	}
-
-	public byte[] sha1Hash(byte[] b) throws OtrCryptoException {
-		try {
-			MessageDigest sha256 = MessageDigest.getInstance("SHA-1");
-			sha256.update(b, 0, b.length);
-			return sha256.digest();
-		} catch (Exception e) {
-			throw new OtrCryptoException(e);
-		}
-	}
-
-	public byte[] aesDecrypt(byte[] key, byte[] ctr, byte[] b)
-			throws OtrCryptoException {
-
-		AESFastEngine aesDec = new AESFastEngine();
-		SICBlockCipher sicAesDec = new SICBlockCipher(aesDec);
-		BufferedBlockCipher bufSicAesDec = new BufferedBlockCipher(sicAesDec);
-
-		// Create initial counter value 0.
-		if (ctr == null)
-			ctr = ZERO_CTR;
-		bufSicAesDec.init(false, new ParametersWithIV(new KeyParameter(key),
-				ctr));
-		byte[] aesOutLwDec = new byte[b.length];
-		int done = bufSicAesDec.processBytes(b, 0, b.length, aesOutLwDec, 0);
-		try {
-			bufSicAesDec.doFinal(aesOutLwDec, done);
-		} catch (Exception e) {
-			throw new OtrCryptoException(e);
-		}
-
-		return aesOutLwDec;
-	}
-
-	public byte[] aesEncrypt(byte[] key, byte[] ctr, byte[] b)
-			throws OtrCryptoException {
-
-		AESFastEngine aesEnc = new AESFastEngine();
-		SICBlockCipher sicAesEnc = new SICBlockCipher(aesEnc);
-		BufferedBlockCipher bufSicAesEnc = new BufferedBlockCipher(sicAesEnc);
-
-		// Create initial counter value 0.
-		if (ctr == null)
-			ctr = ZERO_CTR;
-		bufSicAesEnc.init(true,
-				new ParametersWithIV(new KeyParameter(key), ctr));
-		byte[] aesOutLwEnc = new byte[b.length];
-		int done = bufSicAesEnc.processBytes(b, 0, b.length, aesOutLwEnc, 0);
-		try {
-			bufSicAesEnc.doFinal(aesOutLwEnc, done);
-		} catch (Exception e) {
-			throw new OtrCryptoException(e);
-		}
-		return aesOutLwEnc;
-	}
-
-	public BigInteger generateSecret(PrivateKey privKey, PublicKey pubKey)
-			throws OtrCryptoException {
-		try {
-			KeyAgreement ka = KeyAgreement.getInstance("DH");
-			ka.init(privKey);
-			ka.doPhase(pubKey, true);
-			byte[] sb = ka.generateSecret();
-			BigInteger s = new BigInteger(1, sb);
-			return s;
-
-		} catch (Exception e) {
-			throw new OtrCryptoException(e);
-		}
-	}
-
-	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;
-		for (int i = 0; i < siglen; i++) {
-			if (i < rslen) {
-				if (!writeR)
-					writeR = rb.length >= rslen - i;
-				sig[i] = (writeR) ? rb[i] : (byte) 0x0;
-			} else {
-				int j = i - rslen; // Rebase.
-				if (!writeS)
-					writeS = sb.length >= rslen - j;
-				sig[i] = (writeS) ? sb[j] : (byte) 0x0;
-			}
-		}
-		return sig;
-	}
-
-	public boolean verify(byte[] b, PublicKey pubKey, byte[] rs)
-			throws OtrCryptoException {
-
-		if (!(pubKey instanceof DSAPublicKey))
-			throw new IllegalArgumentException();
-
-		DSAParams dsaParams = ((DSAPublicKey) pubKey).getParams();
-		int qlen = dsaParams.getQ().bitLength() / 8;
-		ByteBuffer buff = ByteBuffer.wrap(rs);
-		byte[] r = new byte[qlen];
-		buff.get(r);
-		byte[] s = new byte[qlen];
-		buff.get(s);
-		return verify(b, pubKey, r, s);
-	}
-
-	private Boolean verify(byte[] b, PublicKey pubKey, byte[] r, byte[] s)
-			throws OtrCryptoException {
-		Boolean result = verify(b, pubKey, new BigInteger(1, r),
-				new BigInteger(1, s));
-		return result;
-	}
-
-	private Boolean verify(byte[] b, PublicKey pubKey, BigInteger r,
-			BigInteger s) throws OtrCryptoException {
-
-		if (!(pubKey instanceof DSAPublicKey))
-			throw new IllegalArgumentException();
-
-		DSAParams dsaParams = ((DSAPublicKey) pubKey).getParams();
-
-		BigInteger q = dsaParams.getQ();
-		DSAParameters bcDSAParams = new DSAParameters(dsaParams.getP(), q,
-				dsaParams.getG());
-
-		DSAPublicKey dsaPrivateKey = (DSAPublicKey) pubKey;
-		DSAPublicKeyParameters dsaPrivParms = new DSAPublicKeyParameters(
-				dsaPrivateKey.getY(), bcDSAParams);
-
-		// 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
-		DSASigner dsaSigner = new DSASigner();
-		dsaSigner.init(false, dsaPrivParms);
-
-		BigInteger bmpi = new BigInteger(1, b);
-		Boolean result = dsaSigner.verifySignature(BigIntegers
-				.asUnsignedByteArray(bmpi.mod(q)), r, s);
-		return result;
-	}
-
-	public String getFingerprint(PublicKey pubKey) throws OtrCryptoException {
-		byte[] b;
-		try {
-			byte[] bRemotePubKey = SerializationUtils.writePublicKey(pubKey);
-
-			if (pubKey.getAlgorithm().equals("DSA")) {
-				byte[] trimmed = new byte[bRemotePubKey.length - 2];
-				System.arraycopy(bRemotePubKey, 2, trimmed, 0, trimmed.length);
-				b = new OtrCryptoEngineImpl().sha1Hash(trimmed);
-			} else
-				b = new OtrCryptoEngineImpl().sha1Hash(bRemotePubKey);
-		} catch (IOException e) {
-			throw new OtrCryptoException(e);
-		}
-		return this.byteArrayToHexString(b);
-	}
-
-	private String byteArrayToHexString(byte in[]) {
-		byte ch = 0x00;
-		int i = 0;
-		if (in == null || in.length <= 0)
-			return null;
-		String pseudo[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
-				"A", "B", "C", "D", "E", "F" };
-		StringBuffer out = new StringBuffer(in.length * 2);
-		while (i < in.length) {
-			ch = (byte) (in[i] & 0xF0);
-			ch = (byte) (ch >>> 4);
-			ch = (byte) (ch & 0x0F);
-			out.append(pseudo[(int) ch]);
-			ch = (byte) (in[i] & 0x0F);
-			out.append(pseudo[(int) ch]);
-			i++;
-		}
-
-		String rslt = new String(out);
-		return rslt;
-
-	}
-}