org.bouncycastle.crypto.general.GOST28147 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bc-fips Show documentation
Show all versions of bc-fips Show documentation
The FIPS 140-3 Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms certified to FIPS 140-3 level 1. This jar contains JCE provider and low-level API for the BC-FJA version 2.0.0, FIPS Certificate #4743. Please see certificate for certified platform details.
package org.bouncycastle.crypto.general;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
import org.bouncycastle.crypto.Algorithm;
import org.bouncycastle.crypto.IllegalKeyException;
import org.bouncycastle.crypto.ParametersWithIV;
import org.bouncycastle.crypto.SymmetricKey;
import org.bouncycastle.crypto.SymmetricSecretKey;
import org.bouncycastle.crypto.internal.BlockCipher;
import org.bouncycastle.crypto.internal.BufferedBlockCipher;
import org.bouncycastle.crypto.internal.KeyGenerationParameters;
import org.bouncycastle.crypto.internal.Mac;
import org.bouncycastle.crypto.internal.ValidatedSymmetricKey;
import org.bouncycastle.crypto.internal.modes.AEADBlockCipher;
import org.bouncycastle.crypto.internal.params.KeyParameter;
import org.bouncycastle.crypto.internal.params.KeyParameterImpl;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
/**
* Source class for implementations of GOST28147 based algorithms.
*/
public final class GOST28147
{
/**
* Raw GOST28147 algorithm, can be used for creating general purpose GOST28147 keys.
*/
public static final GeneralAlgorithm ALGORITHM = new GeneralAlgorithm("GOST28147");
private static final EngineProvider ENGINE_PROVIDER;
static
{
EngineProvider provider = new EngineProvider();
provider.createEngine();
ENGINE_PROVIDER = provider;
}
private GOST28147()
{
}
/**
* GOST28147 in electronic code book (ECB) mode.
*/
public static final Parameters ECB = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.ECB));
/**
* GOST28147 in electronic code book mode with PKCS#7/PKCS#5 padding.
*/
public static final Parameters ECBwithPKCS7 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.ECB, Padding.PKCS7));
/**
* GOST28147 in electronic code book mode with ISO10126-2 padding.
*/
public static final Parameters ECBwithISO10126_2 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.ECB, Padding.ISO10126_2));
/**
* GOST28147 in electronic code book mode with X9.23 padding.
*/
public static final Parameters ECBwithX923 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.ECB, Padding.X923));
/**
* GOST28147 in electronic code book mode with ISO7816-4 padding.
*/
public static final Parameters ECBwithISO7816_4 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.ECB, Padding.ISO7816_4));
/**
* GOST28147 in electronic code book mode with trailing bit complement (TBC) padding.
*/
public static final Parameters ECBwithTBC = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.ECB, Padding.TBC));
/**
* GOST28147 in cipher block chaining (CBC) mode.
*/
public static final Parameters CBC = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC));
/**
* GOST28147 in cipher block chaining mode with PKCS#7/PKCS#5 padding.
*/
public static final Parameters CBCwithPKCS7 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC, Padding.PKCS7));
/**
* GOST28147 in cipher block chaining mode with ISO10126-2 padding.
*/
public static final Parameters CBCwithISO10126_2 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC, Padding.ISO10126_2));
/**
* GOST28147 in cipher block chaining mode with X9.23 padding.
*/
public static final Parameters CBCwithX923 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC, Padding.X923));
/**
* GOST28147 in cipher block chaining mode with ISO7816-4 padding.
*/
public static final Parameters CBCwithISO7816_4 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC, Padding.ISO7816_4));
/**
* GOST28147 in cipher block chaining mode with trailing bit complement (TBC) padding.
*/
public static final Parameters CBCwithTBC = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC, Padding.TBC));
/**
* GOST28147 in cipher block chaining mode cipher text stealing type 1.
*/
public static final Parameters CBCwithCS1 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC, Padding.CS1));
/**
* GOST28147 in cipher block chaining mode cipher text stealing type 2.
*/
public static final Parameters CBCwithCS2 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC, Padding.CS2));
/**
* GOST28147 in cipher block chaining mode cipher text stealing type 3.
*/
public static final Parameters CBCwithCS3 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CBC, Padding.CS3));
/**
* GOST28147 in cipher feedback (CFB) mode, 8 bit block size.
*/
public static final Parameters CFB8 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CFB8));
/**
* GOST28147 in cipher feedback (CFB) mode, 64 bit block size.
*/
public static final Parameters CFB64 = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CFB64));
/**
* GOST28147 in output feedback (OFB) mode.
*/
public static final Parameters OFB = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.OFB64));
/**
* GOST28147 in counter (CTR) mode.
*/
public static final Parameters CTR = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.CTR));
/**
* GOST28147 in EAX mode..
*/
public static final AuthParameters EAX = new AuthParameters(new GeneralAlgorithm(ALGORITHM, Mode.EAX));
/**
* GOST28147 cipher-based MAC algorithm.
*/
public static final AuthParameters CMAC = new AuthParameters(new GeneralAlgorithm(ALGORITHM, Mode.CMAC));
/**
* Standard GOST28147 GOST-CFB mode
*/
public static final Parameters GCFB = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.GCFB));
/**
* Standard GOST28147 GOST-OFB mode
*/
public static final Parameters GOFB = new Parameters(new GeneralAlgorithm(ALGORITHM, Mode.GOFB));
/**
* Standard GOST28147 MAC algorithm
*/
public static final AuthParameters MAC = new AuthParameters(new GeneralAlgorithm(ALGORITHM, Mode.GOSTMAC));
/**
* Parameters for general GOST28147 block cipher modes.
*/
public static final class Parameters
extends GeneralParameters
implements ParametersWithIV
{
private final byte[] iv;
private final byte[] sBox;
Parameters(GeneralAlgorithm algorithm)
{
super(algorithm);
this.iv = null;
this.sBox = null;
}
private Parameters(Parameters parameters, boolean isSbox, byte[] data)
{
super(parameters.getAlgorithm());
if (isSbox)
{
this.sBox = data;
this.iv = parameters.iv;
}
else
{
this.sBox = parameters.sBox;
this.iv = data;
}
((Mode)parameters.getAlgorithm().basicVariation()).checkIv(iv, 8);
}
public Parameters withIV(byte[] iv)
{
return new Parameters(this, false, Arrays.clone(iv));
}
public Parameters withIV(SecureRandom random)
{
return new Parameters(this, false, this.getAlgorithm().createDefaultIvIfNecessary(8, random));
}
public byte[] getIV()
{
return Arrays.clone(iv);
}
public Parameters withSBox(byte[] sBox)
{
return new Parameters(this, true, Arrays.clone(sBox));
}
public byte[] getSBox()
{
if (sBox != null)
{
return sBox.clone();
}
return null;
}
}
/**
* Parameters for GOST28147 AEAD and MAC modes.
*/
public static final class AuthParameters
extends GeneralAuthParameters
{
private final byte[] sBox;
private AuthParameters(GeneralAlgorithm algorithm, byte[] iv, int tagLenInBits, byte[] sBox)
{
super(algorithm, 8, iv, tagLenInBits);
this.sBox = sBox;
}
/**
* Base constructor - the algorithm, null IV.
* In this case the tag length defaults to the 64 for CMAC, 32 bits otherwise.
*
* @param algorithm algorithm mode.
*/
AuthParameters(GeneralAlgorithm algorithm)
{
this(algorithm, null, Utils.getDefaultMacSize(algorithm, 64), null); // tag full blocksize or half
}
/**
* Base constructor - the algorithm, null IV.
* In this case the tag length defaults to the 64 for CMAC, 32 bits otherwise.
*
* @param algorithm algorithm mode.
* @param sBox alternate sBox to use.
*/
public AuthParameters(GeneralAlgorithm algorithm, byte[] sBox)
{
this(algorithm, null, Utils.getDefaultMacSize(algorithm, 64), Arrays.clone(sBox)); // tag full blocksize or half
}
protected AuthParameters create(GeneralAlgorithm algorithm, byte[] iv, int macSizeInBits)
{
return new AuthParameters(algorithm, iv, macSizeInBits, this.sBox);
}
public AuthParameters withSBox(byte[] sBox)
{
return new AuthParameters(this.getAlgorithm(), this.iv, macLenInBits, Arrays.clone(sBox));
}
public byte[] getSBox()
{
if (sBox != null)
{
return sBox.clone();
}
return null;
}
}
/**
* GOST28147 key generator.
*/
public static final class KeyGenerator
extends GuardedSymmetricKeyGenerator
{
private final Algorithm algorithm;
private final SecureRandom random;
public KeyGenerator(SecureRandom random)
{
this.algorithm = ALGORITHM;
this.random = random;
}
public KeyGenerator(GeneralParameters algorithm, SecureRandom random)
{
this.algorithm = algorithm.getAlgorithm();
this.random = random;
}
protected SymmetricKey doGenerateKey()
{
CipherKeyGenerator cipherKeyGenerator = new CipherKeyGenerator();
cipherKeyGenerator.init(new KeyGenerationParameters(random, 256));
return new SymmetricSecretKey(algorithm, cipherKeyGenerator.generateKey());
}
}
/**
* Factory for basic GOST28147 encryption/decryption operators.
*/
public static final class OperatorFactory
extends GuardedSymmetricOperatorFactory
{
protected BufferedBlockCipher createCipher(boolean forEncryption, SymmetricKey key, Parameters parameters, SecureRandom random)
{
KeyParameter keyParameter = createGOST28147Parameters(key, parameters.getAlgorithm(), parameters.getSBox());
return CipherUtils.createStandardCipher(forEncryption, keyParameter, ENGINE_PROVIDER, parameters, random);
}
}
/**
* Factory for GOST28147 AEAD encryption/decryption operators.
*/
public static final class AEADOperatorFactory
extends GuardedAEADOperatorFactory
{
@Override
protected AEADBlockCipher createAEADCipher(boolean forEncryption, SymmetricKey key, AuthParameters parameters)
{
KeyParameter keyParameter = createGOST28147Parameters(key, parameters.getAlgorithm(), parameters.sBox);
return CipherUtils.createStandardAEADCipher(forEncryption, keyParameter, ENGINE_PROVIDER, parameters);
}
}
/**
* Factory for producing GOST28147 MAC calculators.
*/
public static final class MACOperatorFactory
extends GuardedMACOperatorFactory
{
@Override
protected Mac createMAC(SymmetricKey key, final AuthParameters parameters)
{
KeyParameter keyParameter = createGOST28147Parameters(key, parameters.getAlgorithm(), parameters.sBox);
return CipherUtils.createStandardMac(keyParameter, ENGINE_PROVIDER, parameters);
}
@Override
protected int calculateMACSize(AuthParameters parameters)
{
return Utils.bitsToBytes(parameters.macLenInBits);
}
}
private static final class EngineProvider
implements org.bouncycastle.crypto.internal.EngineProvider
{
public BlockCipher createEngine()
{
return SelfTestExecutor.validate(ALGORITHM, new GOST28147Engine(), new VariantKatTest()
{
public void evaluate(GOST28147Engine engine)
{
byte[] input = Hex.decode("00112233445566778899aabbccddeeff");
byte[] output = Hex.decode("54410a030c22e4c6a33255fa5f54cc84");
byte[] tmp = new byte[input.length];
KeyParameter key = new KeyParameterImpl(Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
engine.init(true, key);
engine.processBlock(input, 0, tmp, 0);
engine.processBlock(input, 8, tmp, 8);
if (!Arrays.areEqual(output, tmp))
{
fail("Failed self test on encryption");
}
engine.init(false, key);
engine.processBlock(tmp, 0, tmp, 0);
engine.processBlock(tmp, 8, tmp, 8);
if (!Arrays.areEqual(input, tmp))
{
fail("Failed self test on decryption");
}
}
});
}
}
// these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
// This is default S-box!
private static byte Sbox_Default[] = {
0x4, 0xA, 0x9, 0x2, 0xD, 0x8, 0x0, 0xE, 0x6, 0xB, 0x1, 0xC, 0x7, 0xF, 0x5, 0x3,
0xE, 0xB, 0x4, 0xC, 0x6, 0xD, 0xF, 0xA, 0x2, 0x3, 0x8, 0x1, 0x0, 0x7, 0x5, 0x9,
0x5, 0x8, 0x1, 0xD, 0xA, 0x3, 0x4, 0x2, 0xE, 0xF, 0xC, 0x7, 0x6, 0x0, 0x9, 0xB,
0x7, 0xD, 0xA, 0x1, 0x0, 0x8, 0x9, 0xF, 0xE, 0x4, 0x6, 0xC, 0xB, 0x2, 0x5, 0x3,
0x6, 0xC, 0x7, 0x1, 0x5, 0xF, 0xD, 0x8, 0x4, 0xA, 0x9, 0xE, 0x0, 0x3, 0xB, 0x2,
0x4, 0xB, 0xA, 0x0, 0x7, 0x2, 0x1, 0xD, 0x3, 0x6, 0x8, 0x5, 0x9, 0xC, 0xF, 0xE,
0xD, 0xB, 0x4, 0x1, 0x3, 0xF, 0x5, 0x9, 0x0, 0xA, 0xE, 0x7, 0x6, 0x8, 0x2, 0xC,
0x1, 0xF, 0xD, 0x0, 0x5, 0x7, 0xA, 0x4, 0x9, 0x2, 0x3, 0xE, 0x6, 0xB, 0x8, 0xC
};
/*
* class content S-box parameters for encrypting
* getting from, see: http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-01.txt
* http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-02.txt
*/
private static byte[] ESbox_Test = {
0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7, 0xA, 0x6,
0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0, 0xB, 0x5,
0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF, 0x0, 0xB,
0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4, 0x3, 0x8,
0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1, 0xF, 0x4,
0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE, 0x2, 0x4,
0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA, 0x2, 0xD,
0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4, 0x1, 0x8
};
private static byte[] ESbox_A = {
0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0, 0xD, 0x5,
0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4, 0xD, 0x1,
0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7, 0x1, 0x9,
0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8, 0x5, 0x6,
0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7, 0xA, 0x6,
0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF, 0xE, 0x6,
0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3, 0xB, 0xE,
0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7, 0xD, 0x4
};
private static byte[] ESbox_B = {
0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6, 0x7, 0xF,
0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8, 0x6, 0xE,
0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6, 0x1, 0x4,
0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE, 0x9, 0x8,
0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8, 0xE, 0x3,
0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0, 0x9, 0x5,
0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF, 0x8, 0xE,
0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD, 0x5, 0xC
};
private static byte[] ESbox_C = {
0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7, 0x6, 0x3,
0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA, 0x6, 0x3,
0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE, 0x1, 0xB,
0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF, 0xC, 0x4,
0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF, 0xA, 0x7,
0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0, 0xF, 0xD,
0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1, 0xC, 0x7,
0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9, 0x3, 0x8
};
private static byte[] ESbox_D = {
0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB, 0x8, 0x3,
0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA, 0x9, 0x1,
0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3, 0x7, 0x2,
0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3, 0xF, 0x8,
0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE, 0xF, 0x1,
0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9, 0xD, 0x6,
0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA, 0x5, 0x7,
0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD, 0x2, 0xE
};
// Rosstandart param-Z
private static byte Param_Z[] = {
0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3, 0xf, 0x1,
0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd, 0x0, 0xf,
0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9, 0x6, 0x0,
0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe, 0x9, 0xb,
0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4, 0x2, 0xc,
0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3, 0xe, 0x0,
0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa, 0x3, 0x7,
0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc, 0xb, 0x2
};
//S-box for digest
private static byte DSbox_Test[] = {
0x4, 0xA, 0x9, 0x2, 0xD, 0x8, 0x0, 0xE, 0x6, 0xB, 0x1, 0xC, 0x7, 0xF, 0x5, 0x3,
0xE, 0xB, 0x4, 0xC, 0x6, 0xD, 0xF, 0xA, 0x2, 0x3, 0x8, 0x1, 0x0, 0x7, 0x5, 0x9,
0x5, 0x8, 0x1, 0xD, 0xA, 0x3, 0x4, 0x2, 0xE, 0xF, 0xC, 0x7, 0x6, 0x0, 0x9, 0xB,
0x7, 0xD, 0xA, 0x1, 0x0, 0x8, 0x9, 0xF, 0xE, 0x4, 0x6, 0xC, 0xB, 0x2, 0x5, 0x3,
0x6, 0xC, 0x7, 0x1, 0x5, 0xF, 0xD, 0x8, 0x4, 0xA, 0x9, 0xE, 0x0, 0x3, 0xB, 0x2,
0x4, 0xB, 0xA, 0x0, 0x7, 0x2, 0x1, 0xD, 0x3, 0x6, 0x8, 0x5, 0x9, 0xC, 0xF, 0xE,
0xD, 0xB, 0x4, 0x1, 0x3, 0xF, 0x5, 0x9, 0x0, 0xA, 0xE, 0x7, 0x6, 0x8, 0x2, 0xC,
0x1, 0xF, 0xD, 0x0, 0x5, 0x7, 0xA, 0x4, 0x9, 0x2, 0x3, 0xE, 0x6, 0xB, 0x8, 0xC
};
private static byte DSbox_A[] = {
0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2, 0xB, 0xF,
0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE, 0xA, 0x8,
0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA, 0x8, 0xD,
0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB, 0x9, 0x3,
0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD, 0x3, 0x5,
0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE, 0xC, 0x3,
0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2, 0x9, 0xB,
0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0, 0x2, 0xC
};
//
// pre-defined sbox table
//
private static Map sBoxes = new HashMap();
static
{
addSBox("Default", Sbox_Default);
addSBox("E-TEST", ESbox_Test);
addSBox("E-A", ESbox_A);
addSBox("E-B", ESbox_B);
addSBox("E-C", ESbox_C);
addSBox("E-D", ESbox_D);
addSBox("Param-Z", Param_Z);
addSBox("D-TEST", DSbox_Test);
addSBox("D-A", DSbox_A);
}
private static void addSBox(String sBoxName, byte[] sBox)
{
sBoxes.put(Strings.toUpperCase(sBoxName), sBox);
}
/**
* Return the S-Box associated with SBoxName
*
* @param sBoxName name of the S-Box
* @return byte array representing the S-Box
*/
public static byte[] getSBox(
String sBoxName)
{
byte[] sBox = (byte[])sBoxes.get(Strings.toUpperCase(sBoxName));
if (sBox == null)
{
throw new IllegalArgumentException("Unknown S-Box - possible types: "
+ "\"Default\", \"E-Test\", \"E-A\", \"E-B\", \"E-C\", \"E-D\", \"Param-Z\", \"D-Test\", \"D-A\".");
}
return Arrays.clone(sBox);
}
/**
* Return the S-Box associated with SBox OID.
*
* @param sBoxOID an object identifier associated with an S-Box.
* @return byte array representing the S-Box
*/
public static byte[] getSBox(
ASN1ObjectIdentifier sBoxOID)
{
return getSBox(getSBoxName(sBoxOID));
}
public static String getSBoxName(ASN1ObjectIdentifier oid)
{
String name = oidMappings.get(oid);
if (name == null)
{
throw new IllegalArgumentException("Unknown SBOX OID: " + oid);
}
return name;
}
public static ASN1ObjectIdentifier getSBoxOID(String name)
{
ASN1ObjectIdentifier oid = nameMappings.get(name);
if (oid == null)
{
throw new IllegalArgumentException("Unknown SBOX name: " + name);
}
return oid;
}
public static ASN1ObjectIdentifier getSBoxOID(byte[] sBox)
{
for (Map.Entry name : sBoxes.entrySet())
{
byte[] sb = name.getValue();
if (Arrays.areEqual(sb, sBox))
{
return getSBoxOID(name.getKey());
}
}
throw new IllegalArgumentException("SBOX provided did not map to a known one");
}
private static Map oidMappings = new HashMap();
private static Map nameMappings = new HashMap();
static
{
oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_TestParamSet, "E-TEST");
oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_A_ParamSet, "E-A");
oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_B_ParamSet, "E-B");
oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_C_ParamSet, "E-C");
oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_D_ParamSet, "E-D");
oidMappings.put(RosstandartObjectIdentifiers.id_tc26_gost_28147_param_Z, "Param-Z");
nameMappings.put("E-A", CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_A_ParamSet);
nameMappings.put("E-B", CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_B_ParamSet);
nameMappings.put("E-C", CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_C_ParamSet);
nameMappings.put("E-D", CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_D_ParamSet);
nameMappings.put("Param-Z", RosstandartObjectIdentifiers.id_tc26_gost_28147_param_Z);
}
private static KeyParameter createGOST28147Parameters(SymmetricKey key, Algorithm algorithm, byte[] sBox)
{
return validateKey(key, algorithm, sBox);
}
private static GOST28147Parameters validateKey(SymmetricKey key, Algorithm genAlgorithm, byte[] sBox)
{
ValidatedSymmetricKey vKey = PrivilegedUtils.getValidatedKey(key);
int keyLength = vKey.getKeySizeInBits();
if (keyLength != 256)
{
throw new IllegalKeyException("GOST28147 key must be of length 256 bits");
}
Utils.checkKeyAlgorithm(vKey, ALGORITHM, genAlgorithm);
return new GOST28147Parameters(vKey.getKeyBytes(), sBox);
}
}