Last active
November 29, 2021 20:40
-
-
Save 0x9090/b3b68ba3d9b6f7d08cbec7356a92fe47 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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