Skip to content

Instantly share code, notes, and snippets.

@0x9090
Last active November 29, 2021 20:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0x9090/b3b68ba3d9b6f7d08cbec7356a92fe47 to your computer and use it in GitHub Desktop.
Save 0x9090/b3b68ba3d9b6f7d08cbec7356a92fe47 to your computer and use it in GitHub Desktop.
package anon.app.core.security;
import anon.market.core.Log;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.generators.SCrypt;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jcajce.provider.digest.SHA3;
import javax.ws.rs.WebApplicationException;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;
public class Cryptography {
private static String cryptoSeed;
private static final int aesKeySize = 256;
private static final int nonceBitSize = 128;
private static final int macBitSize = 128;
private static final int ivSize = nonceBitSize / 8;
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
public Cryptography(String seed) {
cryptoSeed = seed;
}
public static String encrypt(String plainText, byte[] key) {
byte[] plainTextBytes = plainText.getBytes(StandardCharsets.UTF_8);
byte[] iv = newIV();
GCMBlockCipher cipher = new GCMBlockCipher(new AESEngine());
AEADParameters parameters = new AEADParameters(new KeyParameter(key), macBitSize, iv, null);
cipher.init(true, parameters);
byte[] encryptedBytes = new byte[cipher.getOutputSize(plainTextBytes.length)];
int returnLength = cipher.processBytes(plainTextBytes, 0, plainTextBytes.length, encryptedBytes, 0);
try {
cipher.doFinal(encryptedBytes, returnLength);
} catch (Exception e) {
Log.write(e.getMessage(), 4);
throw new WebApplicationException(400);
}
byte[] outputBytes = new byte[encryptedBytes.length + iv.length];
System.arraycopy(encryptedBytes, 0, outputBytes, 0, encryptedBytes.length);
System.arraycopy(iv, 0, outputBytes, encryptedBytes.length, iv.length);
return base64Encode(outputBytes);
}
public static String decrypt(String cipherText, byte[] key) {
byte[] cipherTextBytes = base64Decode(cipherText);
byte[] iv = Arrays.copyOfRange(cipherTextBytes, (cipherTextBytes.length - ivSize), cipherTextBytes.length);
byte[] encryptedBytes = Arrays.copyOfRange(cipherTextBytes, 0, (cipherTextBytes.length - ivSize));
GCMBlockCipher cipher = new GCMBlockCipher(new AESEngine());
AEADParameters parameters = new AEADParameters(new KeyParameter(key), macBitSize, iv, null);
cipher.init(false, parameters);
byte[] plainTextBytes = new byte[cipher.getOutputSize(encryptedBytes.length)];
int returnLength = cipher.processBytes(encryptedBytes, 0, encryptedBytes.length, plainTextBytes, 0);
try {
cipher.doFinal(plainTextBytes, returnLength);
} catch (Exception e) {
Log.write(e.getMessage(), 4);
return null;
}
return new String(plainTextBytes, StandardCharsets.UTF_8);
}
public static byte[] base64Decode(String input) {
return Base64.getDecoder().decode(input);
}
public static String base64Encode(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
private static byte[] HexToByte(String hexStr) {
int len = hexStr.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4)
+ Character.digit(hexStr.charAt(i + 1), 16));
}
return data;
}
private static String ByteToHex(byte[] data) {
final StringBuilder builder = new StringBuilder();
for (byte b : data) {
builder.append(Integer.toString(b, 16));
}
return builder.toString();
}
public byte[] newKey(String seed) {
String hash = sha3(seed);
byte[] salt = getSalt().getBytes(StandardCharsets.UTF_8);
byte[] hashBytes = hash.getBytes(StandardCharsets.UTF_8);
byte[] hashedKey = SCrypt.generate(hashBytes, salt, 16384, 8, 8, aesKeySize);
return hashedKey;
}
public static byte[] newIV() {
byte[] iv = new byte[ivSize];
SECURE_RANDOM.nextBytes(iv);
return iv;
}
private static String randomChars(int length, char[] charsArray) {
SecureRandom random = new SecureRandom();
StringBuilder output = new StringBuilder();
for (int i = 0; i < length; i++) {
char selected = charsArray[random.nextInt(charsArray.length)];
output.append(selected);
}
return output.toString();
}
public static String randomAlphaNum(int length) {
// https://stackoverflow.com/a/7111735
char[] charsArray = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
'x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W',
'X','Y','Z', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
return randomChars(length, charsArray);
}
public static String randomAlpha(int length) {
char[] charsArray = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
'x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W',
'X','Y','Z'};
return randomChars(length, charsArray);
}
public static String randomAlphaLower(int length) {
char[] charsArray = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
'x','y','z'};
return randomChars(length, charsArray);
}
public static String sha3(String input) {
final SHA3.DigestSHA3 sha3 = new SHA3.Digest512();
sha3.update(input.getBytes(StandardCharsets.UTF_8));
StringBuilder buff = new StringBuilder();
for (byte b : sha3.digest()) {
buff.append(String.format("%02x", b & 0xFF));
}
return buff.toString();
}
public String passwordHash(String input) {
ByteArrayOutputStream saltedBytes = new ByteArrayOutputStream();
try {
saltedBytes.write(getSalt().getBytes(StandardCharsets.UTF_8));
saltedBytes.write(input.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
Log.write("Could not concatenate the salted bytes", 2);
throw new WebApplicationException(400);
}
byte[] sCryptHash = SCrypt.generate(saltedBytes.toByteArray(), cryptoSeed.getBytes(),16384,8,8,32);
return base64Encode(sCryptHash);
}
public String getCryptoSeed() {
return cryptoSeed;
}
public String getSalt() {
String hashedCryptoSeed = sha3(getCryptoSeed());
return hashedCryptoSeed.substring(0, 5);
}
public static int getAesKeySizeBytes() {
return aesKeySize / 8;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment