Block Ciphers are supported via the GordianCipherFactory interface.
GordianKnot supports most Symmetric Block Ciphers available from BouncyCastle plus some additional ciphers.
A cipher for block encryption/decryption is created by specifying a GordianSymCipherSpec which comprises the GordianSymKeySpec (algorithm/blockSize/keySize) with the cipherMode and padding (if required). The cipher can be used in much the same way as a JCA Cipher, allowing init, update and finalise methods.
A cipher for blockCipher keyWrapping is created by specifying the symKey. The cipher allows init, secure and derive methods
A keyGenerator for a GordianSymKeySpec can be created, which can be used to generate random keys for the keySpec
JCA provides a subset of available algorithms as indicated
Algorithms are represented by GordianSymKeySpec. A GordianKeyGenerator is obtained via the keySpec, and then keys are generated by the generator.
/* Access factory */ final GordianFactory myBaseFactory = GordianGenerator.createFactory(); final GordianCipherFactory myCipherFactory = myBaseFactory.getCipherFactory(); /* Access keyGenerator */ final GordianSymKeySpec mySpec = GordianSymKeySpec.aes(GordianLength.LEN_256); final GordianKeyGenerator<GordianSymKeySpec> myGenerator = myCipherFactory.getKeyGenerator(mySpec); final GordianKey<GordianSymKeySpec> myKey = myGenerator.generateKey();
The following symKey algorithms are supported.
Algorithm | BlockSize | JCA | 128 | 192 | 256 | 512 | 1024 | |
---|---|---|---|---|---|---|---|---|
AES | 128 | Y | Y | Y | Y | |||
Serpent | 128 | Y | Y | Y | Y | |||
TwoFish | 128 | Y | Y | Y | Y | |||
Camellia | 128 | Y | Y | Y | Y | |||
CAST6 | 128 | Y | Y | Y | Y | |||
RC6 | 128 | Y | Y | Y | Y | |||
ARIA | 128 | Y | Y | Y | Y | |||
Kalyna | 128 | Y | Y | Y | ||||
256 | Y | Y | Y | |||||
Kuznyechik | 128 | Y | Y | |||||
ThreeFish | 256 | Y | Y | Y | Y | |||
NoeKeon | 64 | Y | Y | |||||
SM4 | 64 | Y | Y | |||||
SEED | 64 | Y | Y | |||||
SKIPJACK | 64 | Y | Y | |||||
BlowFish | 64 | Y | Y | Y | Y | |||
RC2 | 64 | Y | Y | Y | Y | Y | Y | |
DESede | 64 | Y | Y | Y | ||||
CAST5 | 64 | Y | Y | |||||
RC5 | 64 | Y | Y | |||||
128 | Y | Y | ||||||
IDEA | 64 | Y | Y | |||||
TEA | 64 | Y | Y | |||||
XTEA | 64 | Y | Y | |||||
Magma | 64 | Y | Y | |||||
SHACAL2 | 256 | Y | Y | Y | ||||
Speck | 128 | Y | Y | Y | ||||
Simon | 128 | Y | Y | Y | ||||
MARS | 128 | Y | Y | Y | ||||
Anubis | 128 | Y | Y | Y | ||||
LEA | 128 | Y | Y | Y |
Cipher Algorithms are represented by GordianSymCipherSpec. A GordianSymCipher is obtained via the cipherSpec, and then messages are encrypted/decrypted by the cipher.
/* Access factory */ final GordianFactory myBaseFactory = GordianGenerator.createFactory(); final GordianCipherFactory myCipherFactory = myBaseFactory.getCipherFactory(); /* Create key */ final GordianSymKeySpec myKeySpec = GordianSymKeySpec.aes(GordianLength.LEN_256); final GordianKeyGenerator<GordianSymKeySpec> myGenerator = myCipherFactory.getKeyGenerator(myKeySpec); final GordianKey<GordianSymKeySpec> myKey = myGenerator.generateKey(); /* Create cipher */ final GordianSymCipherSpec myCipherSpec = GordianSymCipherSpec.cbc(myKeySpec, GordianPadding.PKCS7); final GordianSymCipher myCipher = myCipherFactory.createSymKeyCipher(myCipherSpec); /* Encrypt message with random nonce */ GordianCipherParameters myParams = GordianCipherParameters.keyWithRandomNonce(myKey); myCipher.initForEncrypt(myParams); final byte[] myMessage = ... int myOutLen = myCipher.getOutputLength(myMessage.length); final byte[] myEncrypted = new byte[myOutLen]; int myProcessed = myCipher.update(myMessage, 0, myMessage.length, myEncrypted); myCipher.finish(myEncrypted, myProcessed); /* Decrypt message */ myParams = GordianCipherParameters.keyWithNonce(myKey, myCipher.getNonce()); myCipher.initForDecrypt(myParams); myOutLen = myCipher.getOutputLength(myEncrypted.length); final byte[] myResult = new byte[myOutLen]; myProcessed = myCipher.update(myEncrypted, 0, myEncrypted.length, myResult); myCipher.finish(myResult, myProcessed);
The following modes can be used
Mode | JCA | Notes |
---|---|---|
ECB | Y | |
CBC | Y | JCA does not support for Kuznyechik |
G3413CBC | Y | Only available for Kuznyechik |
SIC | Y | |
KCTR | Y | Only available for Kalyna |
G3413CTR | Y | Only available for Kuznyechik |
OFB | Y | Jca does not support for Magma and Kuznyechik |
GOFB | Only available for Magma | |
G3413OFB | Y | Only available for Kuznyechik |
CFB | Y | Jca does not support for Magma and Kuznyechik |
GCFB | Only available for Magma | |
G3413CFB | Y | Only available for Kuznyechik |
CCM | Y | Jca does not support for Kalyna |
KCCM | Only available for Kalyna | |
GCM | Y | Jca does not support for Kalyna |
KGCM | Only available for Kalyna | |
EAX | Y | |
OCB | Y | JCA does not support for Kuznyechik or Kalyna |
GCMSIV | Only available for 128-bit/256-bit keys and 128-bit blocks |
The following paddings can be used for ECB and CBC modes
Padding | JCA | Notes |
---|---|---|
CTS | Y | |
ISO7816-4 | Y | |
PKCS7 | Y | |
X9.63 | Y | |
TBC | Y | |
NONE | Y | Implicitly used for modes other than ECB/CBC |
Key Wrapping is performed by GordianKnot using a variant of the AES Key Wrapping algorithm specified in RFC 5649
The differences are necessary to enable support of ciphers that do not have the standard blockSize of 128 bits, since RFC 5649 assumes a 128 bit blockSize.
In addition, a block of random data is inserted immediately prior to the data to be wrapped.
/* Access factory */ final GordianFactory myBaseFactory = GordianGenerator.createFactory(); final GordianCipherFactory myCipherFactory = myBaseFactory.getCipherFactory(); /* Create keys */ final GordianSymKeySpec myKeySpec = GordianSymKeySpec.aes(GordianLength.LEN_256); final GordianKeyGenerator<GordianSymKeySpec> myGenerator = myCipherFactory.getKeyGenerator(myKeySpec); final GordianKey<GordianSymKeySpec> myKey = myGenerator.generateKey(); final GordianKey<GordianSymKeySpec> myKeyToWrap = myGenerator.generateKey(); /* Create keyWrapper */ final GordianKeyWrapper myWrapper = myCipherFactory.createSymKeyCipher(myKey); /* Secure key */ final byte[] myWrapped = myWrapper.secureKey(myKeyToWrap); /* Derive Key */ final GordianKey<GordianSymKeySpec> myResult = myWrapper.deriveKey(myWrapped, myKeySpec);