All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gs.api.accelrx.crypto.bouncycastle.BouncyCastleGCMObfuscation Maven / Gradle / Ivy

The newest version!
package com.gs.api.accelrx.crypto.bouncycastle;

import com.gs.api.accelrx.crypto.messagedigest.BlockingMessageDigestSha512HashingProvider;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.io.CipherOutputStream;
import org.bouncycastle.crypto.modes.AEADBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class BouncyCastleGCMObfuscation {
    private static final int BASE_HEADER_SIZE = (Long.SIZE / Byte.SIZE) + (Integer.SIZE / Byte.SIZE);
    private static final long VERSION = 1L;

    private final byte[][] salts;
    private final int keyLength;
    private final int ivLength;

    private final int masterKeyIndex;
    private final byte[] masterKey;
    private byte[] masterKeyIV;
    private byte[] otkey;
    private byte[] otkiv;

    private BouncyCastleGCMObfuscation(byte[][] masterKeys, byte[][] salts, int keyLength, int ivLength) {
        this.masterKey = masterKeys[0];
        this.masterKeyIndex = 0;
        this.salts = salts;
        this.keyLength = keyLength;
        this.ivLength = ivLength;
    }

    public static BouncyCastleGCMObfuscation create(byte[][] masterKeys, byte[][] salts, int keyLength, int ivLength) {
        return new BouncyCastleGCMObfuscation(masterKeys, salts, keyLength, ivLength);
    }

    public byte[] obfuscate(byte[] message) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        writeObfuscationHeaderFields(baos, message);

        AEADBlockCipher messageCipher = getCipher(otkey, otkiv, true);
        encryptBytesToStream(baos, message, messageCipher);

        baos.flush();
        return baos.toByteArray();
    }

    private void writeObfuscationHeaderFields(ByteArrayOutputStream baos, byte[] message) throws IOException {
        this.masterKeyIV = deterministicBytes(message, salts[0], ivLength);
        this.otkey = deterministicBytes(message, salts[1], keyLength);
        this.otkiv = deterministicBytes(message, salts[2], ivLength);

        AEADBlockCipher headerCipher = getCipher(masterKey, masterKeyIV, true);
        baos.write(header(headerCipher));
    }

    private byte[] header(AEADBlockCipher cipher) throws IOException {
        ByteBuffer bb = ByteBuffer.allocate(BASE_HEADER_SIZE + (keyLength + 16) + (ivLength * 2));
        bb.putLong(VERSION);
        bb.putInt(masterKeyIndex);
        bb.put(masterKeyIV);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        encryptBytesToStream(baos, otkey, cipher);
        byte[] encryptedKey = baos.toByteArray();

        bb.put(encryptedKey);
        bb.put(otkiv);
        return bb.array();
    }

    private void encryptBytesToStream(OutputStream outputStream, byte[] bytes, AEADBlockCipher cipher) throws IOException {
        try (CipherOutputStream cipherStream = new CipherOutputStream(outputStream, cipher)) {
            cipherStream.write(bytes);
        }
    }

    private AEADBlockCipher getCipher(byte[] key, byte[] iv, boolean forEncryption) {
        AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine());
        cipher.init(forEncryption, new AEADParameters(new KeyParameter(key), 128, iv));
        return cipher;
    }

    private byte[] deterministicBytes(byte[] message, byte[] salt, int length) {
        BlockingMessageDigestSha512HashingProvider hashingProvider = BlockingMessageDigestSha512HashingProvider.create(salt);
        String hash = hashingProvider.hash(message);
        return Arrays.copyOfRange(hash.getBytes(StandardCharsets.UTF_8), 0, length);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy