package network.thunder.core.etc.crypto;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Sha256Hash;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Arrays;
/**
* Created by matsjerratsch on 12/10/2015.
*/
public class CryptoTools {
public static byte[] addHMAC (byte[] data, byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeyException {
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(keySpec);
byte[] result = mac.doFinal(data);
byte[] total = new byte[result.length + data.length];
System.arraycopy(result, 0, total, 0, result.length);
System.arraycopy(data, 0, total, result.length, data.length);
return total;
}
public static byte[] getHMAC (byte[] data, byte[] keyBytes) {
try {
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(keySpec);
return mac.doFinal(data);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void checkHMAC (byte[] hmac, byte[] rest, byte[] keyBytes) {
try {
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(keySpec);
byte[] result = mac.doFinal(rest);
if (!Arrays.equals(result, hmac)) {
throw new RuntimeException("HMAC does not match..");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] createSignature (ECKey pubkey, byte[] data) throws NoSuchProviderException, NoSuchAlgorithmException {
return pubkey.sign(Sha256Hash.of(data)).encodeToDER();
}
public static byte[] decryptAES_CTR (byte[] data, byte[] keyBytes, byte[] ivBytes, long counter) {
try {
// byte[] keyBytes = new byte[]{(byte) 0x36, (byte) 0xf1, (byte) 0x83, (byte) 0x57, (byte) 0xbe, (byte) 0x4d, (byte) 0xbd, (byte) 0x77, (byte) 0xf0,
// (byte) 0x50, (byte) 0x51, (byte) 0x5c, 0x73, (byte) 0xfc, (byte) 0xf9, (byte) 0xf2};
// byte[] ivBytes = new byte[]{(byte) 0x69, (byte) 0xdd, (byte) 0xa8, (byte) 0x45, (byte) 0x5c, (byte) 0x7d, (byte) 0xd4, (byte) 0x25, (byte) 0x4b,
// (byte) 0xf3, (byte) 0x53, (byte) 0xb7, (byte) 0x73, (byte) 0x30, (byte) 0x4e, (byte) 0xec};
byte[] ivWithCounter = new byte[16];
System.arraycopy(ivBytes, 0, ivWithCounter, 0, ivBytes.length);
byte[] counterBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(counter).array();
System.arraycopy(counterBytes, 0, ivWithCounter, ivBytes.length, counterBytes.length);
//Initialisation
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivWithCounter);
//Mode
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] plain = cipher.doFinal(data);
String plaintext = new String(plain);
// System.out.println("plaintext: " + plaintext);
return plain;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] encryptAES_CTR (byte[] data, byte[] keyBytes, byte[] ivBytes, long counter) {
try {
// byte[] keyBytes = new byte[]{(byte) 0x36, (byte) 0xf1, (byte) 0x83, (byte) 0x57, (byte) 0xbe, (byte) 0x4d, (byte) 0xbd, (byte) 0x77, (byte) 0xf0,
// (byte) 0x50, (byte) 0x51, (byte) 0x5c, 0x73, (byte) 0xfc, (byte) 0xf9, (byte) 0xf2};
// byte[] ivBytes = new byte[]{(byte) 0x69, (byte) 0xdd, (byte) 0xa8, (byte) 0x45, (byte) 0x5c, (byte) 0x7d, (byte) 0xd4, (byte) 0x25, (byte) 0x4b,
// (byte) 0xf3, (byte) 0x53, (byte) 0xb7, (byte) 0x73, (byte) 0x30, (byte) 0x4e, (byte) 0xec};
byte[] ivWithCounter = new byte[16];
System.arraycopy(ivBytes, 0, ivWithCounter, 0, ivBytes.length);
byte[] counterBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(counter).array();
System.arraycopy(counterBytes, 0, ivWithCounter, ivBytes.length, counterBytes.length);
//Initialisation
// System.out.println(keyBytes.length);
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivWithCounter);
// System.out.println(key);
//Mode
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] original = cipher.doFinal(data);
String plaintext = new String(original);
// System.out.println("plaintext: " + plaintext);
return original;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void verifySignature (ECKey pubkey, byte[] data, byte[] signature) throws NoSuchProviderException, NoSuchAlgorithmException {
MessageDigest hashHandler = MessageDigest.getInstance("SHA256", "BC");
hashHandler.update(data);
byte[] hash = hashHandler.digest();
if (!pubkey.verify(hash, signature)) {
System.out.println("Signature does not match..");
throw new RuntimeException("Signature does not match..");
}
}
public static ECKey getEphemeralKey () {
return new ECKey();
}
}