package org.thoughtcrime.SMP.crypto.SMP;
/**
* Created by ludwig on 29/06/15.
*/
/*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @author George Politis
*
*/
public class SMPCryptoEngineImpl /*implements SMPCryptoEngine*/ {
/*
public KeyPair generateDHKeyPair() throws SMPCryptoException {
// 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 SMPCryptoException(e);
}
}
public DHPublicKey getDHPublicKey(byte[] mpiBytes)
throws SMPCryptoException {
return getDHPublicKey(new BigInteger(mpiBytes));
}
public DHPublicKey getDHPublicKey(BigInteger mpi) throws SMPCryptoException {
DHPublicKeySpec pubKeySpecs = new DHPublicKeySpec(mpi, MODULUS,
GENERATOR);
try {
KeyFactory keyFac = KeyFactory.getInstance("DH");
return (DHPublicKey) keyFac.generatePublic(pubKeySpecs);
} catch (Exception e) {
throw new SMPCryptoException(e);
}
}
public byte[] sha256Hmac(byte[] b, byte[] key) throws SMPCryptoException {
return this.sha256Hmac(b, key, 0);
}
public byte[] sha256Hmac(byte[] b, byte[] key, int length)
throws SMPCryptoException {
SecretKeySpec keyspec = new SecretKeySpec(key, "HmacSHA256");
javax.crypto.Mac mac;
try {
mac = javax.crypto.Mac.getInstance("HmacSHA256");
} catch (NoSuchAlgorithmException e) {
throw new SMPCryptoException(e);
}
try {
mac.init(keyspec);
} catch (InvalidKeyException e) {
throw new SMPCryptoException(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 SMPCryptoException {
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 SMPCryptoException(e);
}
}
public byte[] sha256Hmac160(byte[] b, byte[] key) throws SMPCryptoException {
return sha256Hmac(b, key, 20);
}
public byte[] sha256Hash(byte[] b) throws SMPCryptoException {
try {
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
sha256.update(b, 0, b.length);
return sha256.digest();
} catch (Exception e) {
throw new SMPCryptoException(e);
}
}
public byte[] sha1Hash(byte[] b) throws SMPCryptoException {
try {
MessageDigest sha256 = MessageDigest.getInstance("SHA-1");
sha256.update(b, 0, b.length);
return sha256.digest();
} catch (Exception e) {
throw new SMPCryptoException(e);
}
}
public byte[] aesDecrypt(byte[] key, byte[] ctr, byte[] b)
throws SMPCryptoException {
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 SMPCryptoException(e);
}
return aesOutLwDec;
}
public byte[] aesEncrypt(byte[] key, byte[] ctr, byte[] b)
throws SMPCryptoException {
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 SMPCryptoException(e);
}
return aesOutLwEnc;
}
public BigInteger generateSecret(PrivateKey privKey, PublicKey pubKey)
throws SMPCryptoException {
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 SMPCryptoException(e);
}
}
public byte[] sign(byte[] b, PrivateKey privatekey)
throws SMPCryptoException {
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];
System.arraycopy(rb, 0, sig, rslen - rb.length, rb.length);
System.arraycopy(sb, 0, sig, sig.length - sb.length, sb.length);
return sig;
}
public boolean verify(byte[] b, PublicKey pubKey, byte[] rs)
throws SMPCryptoException {
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 SMPCryptoException {
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 SMPCryptoException {
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 SMPCryptoException {
byte[] b = getFingerprintRaw(pubKey);
return SerializationUtils.byteArrayToHexString(b);
}
public byte[] getFingerprintRaw(PublicKey pubKey)
throws SMPCryptoException {
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 SMPCryptoEngineImpl().sha1Hash(trimmed);
} else
b = new SMPCryptoEngineImpl().sha1Hash(bRemotePubKey);
} catch (IOException e) {
throw new SMPCryptoException(e);
}
return b;
}
*/
}