public abstract class PKCS11Cipher extends javax.crypto.CipherSpi implements PKCS11EngineClass
Modifier and Type | Field and Description |
---|---|
protected boolean |
currentKeyIsSoftwareKey_
Indiecates that the currently used key is a software key.
|
protected static byte[] |
DUMMY_DATA
Dummy data that we
|
protected boolean |
initialized_
Indicates, if this object is initialized and ready for encryption or decryption.
|
protected IAIKPKCS11Key |
key_
The key to use for encryption/decryption.
|
protected iaik.pkcs.pkcs11.objects.Key |
keyObject_
The PKCS#11 key object of the current key.
|
protected iaik.pkcs.pkcs11.Mechanism |
mechanism_
The current cryptoki mechanism to use.
|
protected java.lang.String |
mode_
The name of the current mode.
|
protected boolean |
modeChanged_
Indicates that the mode has been changed.
|
protected int |
operationMode_
The state of this object; DECRYPT_MODE, ENCRYPT_MODE, UNWRAP_MODE or WRAP_MODE.
|
protected java.lang.String |
padding_
The name of the current padding.
|
protected boolean |
paddingChanged_
Indicates that the padding has been changed.
|
protected java.security.AlgorithmParameters |
parameters_
Any currently used parameter.
|
protected PKCS11Spec |
parameterSpecs_
The parameter specs.
|
protected boolean |
pkcs11OperationInitialized_
Indicates, if the PKCS#11 cipher is already initialized for the next cipher operation round.
|
protected iaik.pkcs.pkcs11.Session |
session_
The session this object works with.
|
protected javax.crypto.Cipher |
softwareDelegate_
The software implementation, if the currently used key is not a PKCS#11 key.
|
protected TokenManager |
tokenManager_
Token manager used to login session, if required.
|
protected iaik.pkcs.pkcs11.objects.Key |
unwrapTemplate_
The unwrap template for an unwrap operation.
|
protected boolean |
updateUsed_
Indicates, if the currently active operation has already used any update function.
|
protected iaik.pkcs.pkcs11.MechanismInfo[][] |
usedMechanismInfos_
The mechanism info is the same for all digest mechanisms.
|
protected iaik.pkcs.pkcs11.Mechanism[] |
usedMechanisms_
The list of used mechanisms.
|
Modifier | Constructor and Description |
---|---|
protected |
PKCS11Cipher()
Default constructor.
|
Modifier and Type | Method and Description |
---|---|
protected abstract void |
checkKeyObject(iaik.pkcs.pkcs11.objects.Key key)
Check the given key object, if it is acceptable for this cipher.
|
protected byte[] |
engineDoFinal(byte[] input,
int inputOffset,
int inputLength)
Update the currently running cipher operation with the given data and finish the current
operation.
|
protected int |
engineDoFinal(byte[] input,
int inputOffset,
int inputLen,
byte[] output,
int outputOffset)
Update the currently running cipher operation with the given data and finish the current
operation.
|
protected int |
engineGetBlockSize()
If initialized with a PKCS#11 key, this method returns -1 by default.
|
protected byte[] |
engineGetIV()
If initialized with a PKCS#11 key, this method returns null by default.
|
protected int |
engineGetKeySize(java.security.Key key)
If initialized with a PKCS#11 key, this method returns -1 by default.
|
protected int |
engineGetOutputSize(int inputLength)
If initialized with a PKCS#11 key, this method returns -1 by default.
|
protected java.security.AlgorithmParameters |
engineGetParameters()
Returns the parameters used with this cipher.
|
protected void |
engineInit(int operationMode,
java.security.Key key,
java.security.spec.AlgorithmParameterSpec parameterSpecs,
java.security.SecureRandom randomSource)
Initialize this cipher for an operation.
|
protected void |
engineInit(int operationMode,
java.security.Key key,
java.security.AlgorithmParameters parameters,
java.security.SecureRandom random)
Initialize this cipher for an operation.
|
protected void |
engineInit(int operationMode,
java.security.Key key,
java.security.SecureRandom randomSource)
Initialize this cipher for an operation.
|
protected void |
engineSetMode(java.lang.String mode)
Set the mode of operation.
|
protected void |
engineSetPadding(java.lang.String padding)
Set the padding scheme.
|
protected java.security.Key |
engineUnwrap(byte[] wrappedKey,
java.lang.String wrappedKeyAlgorithm,
int wrappedKeyType)
Unwrap (decrypt) the given wrapped (encrypted) key.
|
protected byte[] |
engineUpdate(byte[] data,
int offset,
int length)
Update the currently running cipher operation with the given data.
|
protected int |
engineUpdate(byte[] input,
int inputOffset,
int inputLength,
byte[] output,
int outputOffset)
Update the currently running cipher operation with the given data and write the intermediate
result (if any) to the given buffer.
|
protected void |
engineUpdateAAD(byte[] src,
int offset,
int len)
Updates the Additional Authentication Data (AAD) with the given data.
|
protected byte[] |
engineWrap(java.security.Key key)
Wrap (encrypt) the given key.
|
protected void |
finalize()
Tries to close the used session.
|
protected void |
finalizePkcs11Operation()
The internal session finalization method, if the current operation has been finished.
|
protected abstract java.lang.String |
getAlgorithmName()
Get the JCE name of this cipher algorithm.
|
protected abstract iaik.pkcs.pkcs11.Mechanism |
getDefaultMechanism()
Get the default mechanism of this cipher.
|
protected java.lang.String |
getFullAlgorithmName()
Get the JCE name of this cipher algorithm including mode and padding.
|
protected abstract iaik.pkcs.pkcs11.Mechanism |
getMechanism()
Get the current mechanism of this cipher object.
|
protected iaik.pkcs.pkcs11.MechanismInfo[][] |
getUsedMechanismFeatures()
Returns an two-dimensional array of MechanismInfos that this engine class uses.
|
protected iaik.pkcs.pkcs11.Mechanism[] |
getUsedMechanisms()
Returns an array of Mechanisms that this engine class uses.
|
protected void |
initialize()
The internal initialization method, if all necessary member variables are set.
|
protected void |
initializePkcs11Operation()
The internal session initialization method, if all necessary member variables are set.
|
protected void |
initializeSession()
Sets up an appropriate session.
|
protected void |
initializeSoftwareDelegate()
Instantiate a new software cipher to delegate software keys operations.
|
protected abstract boolean |
isModeSupported(java.lang.String mode)
Check, if the given mode of operation is supported by this cipher.
|
protected abstract boolean |
isPaddingSupported(java.lang.String padding)
Check, if the given padding scheme is supported by this cipher.
|
boolean |
isSupportedBy(TokenManager tokenManager)
Check, if the current token of the given token manager supports the required features for this
engine class.
|
protected byte[] |
pkcs11DoFinal(byte[] input,
int inputOffset,
int inputLength)
Update the currently running cipher operation with the given data and finish the current
operation.
|
protected int |
pkcs11DoFinal(byte[] input,
int inputOffset,
int inputLen,
byte[] output,
int outputOffset)
Update the currently running cipher operation with the given data and finish the current
operation.
|
protected int |
pkcs11GetBlockSize()
Get the block size of this cipher algorithm.
|
protected byte[] |
pkcs11GetIV()
Get the currently set initialization vector.
|
protected int |
pkcs11GetKeySize(java.security.Key key)
Determines the key size in bits.
|
protected int |
pkcs11GetOutputSize(int inputLength)
Returns the length in bytes that an output buffer would need to be in order to hold the result
of the next update or doFinal operation, given the input length inputLen (in bytes).
|
protected java.security.AlgorithmParameters |
pkcs11GetParameters()
Returns the parameters used with this cipher.
|
protected void |
pkcs11Init(int operationMode,
java.security.Key key,
java.security.spec.AlgorithmParameterSpec parameterSpecs,
java.security.SecureRandom randomSource)
Initialize this cipher for an operation.
|
protected void |
pkcs11Init(int operationMode,
java.security.Key key,
java.security.AlgorithmParameters parameters,
java.security.SecureRandom random)
Initialize this cipher for an operation.
|
protected void |
pkcs11Init(int operationMode,
java.security.Key key,
java.security.SecureRandom randomSource)
Initialize this cipher for an operation.
|
protected java.security.Key |
pkcs11Unwrap(byte[] wrappedKey,
java.lang.String wrappedKeyAlgorithm,
int wrappedKeyType)
Unwrap (decrypt) the given wrapped (encrypted) key.
|
protected byte[] |
pkcs11Update(byte[] data,
int offset,
int length)
Update the currently running cipher operation with the given data.
|
protected int |
pkcs11Update(byte[] input,
int inputOffset,
int inputLength,
byte[] output,
int outputOffset)
Update the currently running cipher operation with the given data and write
|
protected byte[] |
pkcs11Wrap(java.security.Key key)
Wrap (encrypt) the given key.
|
protected void |
updateAAD(byte[] src) |
protected void |
updateAAD(byte[] src,
int offset,
int len) |
protected void |
updateAAD(java.nio.ByteBuffer src) |
protected static final byte[] DUMMY_DATA
protected iaik.pkcs.pkcs11.Session session_
protected TokenManager tokenManager_
protected IAIKPKCS11Key key_
protected iaik.pkcs.pkcs11.objects.Key keyObject_
protected int operationMode_
protected iaik.pkcs.pkcs11.Mechanism mechanism_
protected boolean initialized_
protected boolean pkcs11OperationInitialized_
protected boolean updateUsed_
protected boolean currentKeyIsSoftwareKey_
protected javax.crypto.Cipher softwareDelegate_
protected java.lang.String mode_
protected java.lang.String padding_
protected java.security.AlgorithmParameters parameters_
protected boolean modeChanged_
protected boolean paddingChanged_
protected iaik.pkcs.pkcs11.Mechanism[] usedMechanisms_
protected iaik.pkcs.pkcs11.MechanismInfo[][] usedMechanismInfos_
protected iaik.pkcs.pkcs11.objects.Key unwrapTemplate_
protected PKCS11Spec parameterSpecs_
protected iaik.pkcs.pkcs11.Mechanism[] getUsedMechanisms()
getRequiredMechanismFeatures()
method.getUsedMechanismFeatures()
. May be empty, but must not be null.protected iaik.pkcs.pkcs11.MechanismInfo[][] getUsedMechanismFeatures()
getUsedMechanisms()
. The array at this index is the list of used feature
combinations used by this engine. The current token must at least support one mechanism and one
of the feature combinations (expressed as a MechanismInfo) of the same mechanism.getUsedMechanisms()
. The token must at
least support one of these features.public boolean isSupportedBy(TokenManager tokenManager)
isSupportedBy
in interface PKCS11EngineClass
tokenManager
- The token manager. Used to get information about the current token.protected abstract void checkKeyObject(iaik.pkcs.pkcs11.objects.Key key) throws java.security.InvalidKeyException
key
- The key object to check.java.security.InvalidKeyException
- If this cipher cannot work with this type of key object.protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException, javax.crypto.ShortBufferException
pkcs11
instead
of engine
.engineDoFinal
in class javax.crypto.CipherSpi
input
- The byte array that holds the input data.inputOffset
- The offset in the input byte array that indicates the first input data byte to read.inputLen
- The number of bytes to read starting from offset.output
- The byte array that receives the final output data.outputOffset
- The offset in the output byte array where to start writing the output.javax.crypto.BadPaddingException
- If the padding of the decrypted data is bad or if the padding of the input data
failed.javax.crypto.IllegalBlockSizeException
- If the input data size does not match the required block size.javax.crypto.ShortBufferException
- If the provided output buffer is too small.protected int pkcs11DoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException, javax.crypto.ShortBufferException
input
- The byte array that holds the input data.inputOffset
- The offset in the input byte array that indicates the first input data byte to read.inputLen
- The number of bytes to read starting from offset.output
- The byte array that receives the final output data.outputOffset
- The offset in the output byte array where to start writing the output.javax.crypto.BadPaddingException
- If the padding of the decrypted data is bad or if the padding of the input data
failed.javax.crypto.IllegalBlockSizeException
- If the input data size does not match the required block size.javax.crypto.ShortBufferException
- If the provided output buffer is too small.protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLength) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException
pkcs11
instead
of engine
.engineDoFinal
in class javax.crypto.CipherSpi
input
- The byte array that holds the input data.inputOffset
- The offset in the input byte array that indicates the first input data byte to read.inputLength
- The number of bytes to read starting from offset.javax.crypto.BadPaddingException
- If the padding of the decrypted data is bad or if the padding of the input data
failed.javax.crypto.IllegalBlockSizeException
- If the input data size does not match the required block size.protected byte[] pkcs11DoFinal(byte[] input, int inputOffset, int inputLength) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException
input
- The byte array that holds the input data.inputOffset
- The offset in the input byte array that indicates the first input data byte to read.inputLength
- The number of bytes to read starting from offset.javax.crypto.BadPaddingException
- If the padding of the decrypted data is bad or if the padding of the input data
failed.javax.crypto.IllegalBlockSizeException
- If the input data size does not match the required block size.protected int engineGetBlockSize()
pkcs11
instead of engine
.engineGetBlockSize
in class javax.crypto.CipherSpi
protected int pkcs11GetBlockSize()
protected byte[] engineGetIV()
pkcs11
instead of engine
.engineGetIV
in class javax.crypto.CipherSpi
protected byte[] pkcs11GetIV()
protected int engineGetKeySize(java.security.Key key) throws java.security.InvalidKeyException
pkcs11
instead of engine
. If the key is not a key of this provider
but is a secret key, it tries to determine the key's length by getting the key's encoding.engineGetKeySize
in class javax.crypto.CipherSpi
key
- The key to check.java.security.InvalidKeyException
- If the given key is not supported by this class; e.g. public and private keys that
are not keys of this provider or secret keys no of this provider which do not
provide an encoding.protected int pkcs11GetKeySize(java.security.Key key) throws java.security.InvalidKeyException
key
- The key to get the length for.java.security.InvalidKeyException
- If the given key is not supported by this class.protected int engineGetOutputSize(int inputLength)
pkcs11
instead of engine
.engineGetOutputSize
in class javax.crypto.CipherSpi
inputLength
- The input data length.protected int pkcs11GetOutputSize(int inputLength)
inputLength
- The length of the input data in bytes.protected java.security.AlgorithmParameters engineGetParameters()
pkcs11
instead of engine
.engineGetParameters
in class javax.crypto.CipherSpi
protected java.security.AlgorithmParameters pkcs11GetParameters()
protected void engineInit(int operationMode, java.security.Key key, java.security.SecureRandom randomSource) throws java.security.InvalidKeyException
pkcs11
instead
of engine
.engineInit
in class javax.crypto.CipherSpi
operationMode
- The operation to initialize; Cipher.ENCRYPT_MODE, Cipher.DECRYPT_MODE,
Cipher.UNWRAP_MODE or Cipher.WRAP_MODE.key
- The key to use for the operation.randomSource
- Optional random source to use.java.security.InvalidKeyException
- If the key is invalid for this operation.protected void pkcs11Init(int operationMode, java.security.Key key, java.security.SecureRandom randomSource) throws java.security.InvalidKeyException
operationMode
- The operation to initialize; Cipher.ENCRYPT_MODE, Cipher.DECRYPT_MODE,
Cipher.UNWRAP_MODE or Cipher.WRAP_MODE.key
- The key to use for the operation.randomSource
- Optional random source to use.java.security.InvalidKeyException
- If the key is invalid for this operation.protected void engineInit(int operationMode, java.security.Key key, java.security.AlgorithmParameters parameters, java.security.SecureRandom random) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException
pkcs11
instead
of engine
.engineInit
in class javax.crypto.CipherSpi
operationMode
- The operation to initialize; Cipher.ENCRYPT_MODE, Cipher.DECRYPT_MODE,
Cipher.UNWRAP_MODE or Cipher.WRAP_MODE.key
- The key to use for the operation.parameters
- The parameters to use. Some cipher do not support parameters, they require null.random
- Optional random source to use.java.security.InvalidAlgorithmParameterException
- If the parameters are invalid.java.security.InvalidKeyException
- If the key is invalid for this operation.protected void pkcs11Init(int operationMode, java.security.Key key, java.security.AlgorithmParameters parameters, java.security.SecureRandom random) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException
pkcs11
instead
of engine
.operationMode
- The operation to initialize; Cipher.ENCRYPT_MODE, Cipher.DECRYPT_MODE,
Cipher.UNWRAP_MODE or Cipher.WRAP_MODE.key
- The key to use for the operation.parameters
- The parameters to use. Some cipher do not support parameters, they require null. This
implementation ignores the parameter.random
- Optional random source to use.java.security.InvalidAlgorithmParameterException
- If the parameters are invalid.java.security.InvalidKeyException
- If the key is invalid for this operation.protected void engineInit(int operationMode, java.security.Key key, java.security.spec.AlgorithmParameterSpec parameterSpecs, java.security.SecureRandom randomSource) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException
pkcs11
instead
of engine
.engineInit
in class javax.crypto.CipherSpi
operationMode
- The operation to initialize; Cipher.ENCRYPT_MODE, Cipher.DECRYPT_MODE,
Cipher.UNWRAP_MODE or Cipher.WRAP_MODE.key
- The key to use for the operation.parameterSpecs
- The parameter specs to use. Some cipher do not support parameter specs, they require
null.randomSource
- Optional random source to use.java.security.InvalidAlgorithmParameterException
- If the parameter specs are invalid.java.security.InvalidKeyException
- If the key is invalid for this operation.protected void pkcs11Init(int operationMode, java.security.Key key, java.security.spec.AlgorithmParameterSpec parameterSpecs, java.security.SecureRandom randomSource) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException
operationMode
- The operation to initialize; Cipher.ENCRYPT_MODE, Cipher.DECRYPT_MODE,
Cipher.UNWRAP_MODE or Cipher.WRAP_MODE.key
- The key to use for the operation.parameterSpecs
- The parameter specs to use. Some cipher do not support parameter specs, they require
null.randomSource
- Optional random source to use.java.security.InvalidAlgorithmParameterException
- If the parameter specs are invalid.java.security.InvalidKeyException
- If the key is invalid for this operation.protected void initializeSoftwareDelegate()
protected abstract java.lang.String getAlgorithmName()
protected java.lang.String getFullAlgorithmName()
protected void initializeSession()
protected void initializePkcs11Operation() throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException
java.security.InvalidAlgorithmParameterException
- If the parameter specs are invalid.java.security.InvalidKeyException
- If the key is invalid for this operation.protected void finalizePkcs11Operation()
protected void initialize() throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException
java.security.InvalidAlgorithmParameterException
- If the parameter specs are invalid.java.security.InvalidKeyException
- If the key is invalid for this operation.protected void engineSetMode(java.lang.String mode) throws java.security.NoSuchAlgorithmException
engineSetMode
in class javax.crypto.CipherSpi
mode
- The mode of operation.java.security.NoSuchAlgorithmException
- If the mode is unsupported.protected abstract boolean isModeSupported(java.lang.String mode)
mode
- The mode to check.protected void engineSetPadding(java.lang.String padding) throws javax.crypto.NoSuchPaddingException
engineSetPadding
in class javax.crypto.CipherSpi
padding
- The padding scheme.javax.crypto.NoSuchPaddingException
- If the padding is unsupported.protected abstract boolean isPaddingSupported(java.lang.String padding)
padding
- The padding scheme to check.protected byte[] engineUpdate(byte[] data, int offset, int length)
pkcs11
instead of engine
.engineUpdate
in class javax.crypto.CipherSpi
data
- The byte array that holds the data.offset
- The offset in the byte array that indicates the first data byte to read.length
- The number of bytes to read starting from offset.protected byte[] pkcs11Update(byte[] data, int offset, int length)
data
- The byte array that holds the data.offset
- The offset in the byte array that indicates the first data byte to read.length
- The number of bytes to read starting from offset.protected int engineUpdate(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws javax.crypto.ShortBufferException
pkcs11
instead
of engine
.engineUpdate
in class javax.crypto.CipherSpi
input
- The byte array that holds the input data.inputOffset
- The offset in the input byte array that indicates the first input data byte to read.inputLength
- The number of bytes to read starting from offset.output
- The byte array that receives the output data.outputOffset
- The offset in the output byte array where to start writing the output.javax.crypto.ShortBufferException
- If the given output buffer does not have enough space left for the produced
output.protected void engineUpdateAAD(byte[] src, int offset, int len)
Only meaningful for AEAD cipher modes like GCM or CCM. Currently only supported for software delegation providers.
engineUpdateAAD
in class javax.crypto.CipherSpi
src
- the data to update the AAD withoffset
- the start offsetlen
- the number AAD bytesprotected int pkcs11Update(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws javax.crypto.ShortBufferException
input
- The byte array that holds the input data.inputOffset
- The offset in the input byte array that indicates the first input data byte to read.inputLength
- The number of bytes to read starting from offset.output
- The byte array that receives the output data.outputOffset
- The offset in the output byte array where to start writing the output.javax.crypto.ShortBufferException
- If the given output buffer does not have enough space left for the produced
output.protected void updateAAD(byte[] src)
protected void updateAAD(byte[] src, int offset, int len)
protected void updateAAD(java.nio.ByteBuffer src)
protected java.security.Key engineUnwrap(byte[] wrappedKey, java.lang.String wrappedKeyAlgorithm, int wrappedKeyType) throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
pkcs11
instead of engine
.engineUnwrap
in class javax.crypto.CipherSpi
wrappedKey
- The wrapped (encrypted) key to be unwrapped (decrypted).wrappedKeyAlgorithm
- Ignored in this implementation.wrappedKeyType
- Ignored in this implementation.java.security.NoSuchAlgorithmException
- If keys of the specified algorithm are unsupported.java.security.InvalidKeyException
- If the given wrapped key is invalid.protected java.security.Key pkcs11Unwrap(byte[] wrappedKey, java.lang.String wrappedKeyAlgorithm, int wrappedKeyType) throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
wrappedKey
- The wrapped (encrypted) key to be unwrapped (decrypted).wrappedKeyAlgorithm
- This may be any key type name of the ones defined in the IAIKPKCS11Key class.wrappedKeyType
- This may be Cipher.SECRET_KEY, Cipher.PRIVATE_KEY or Cipher.PUBLIC_KEY. If this is -1,
no key template will be passed to the PKCS#11 library.java.security.NoSuchAlgorithmException
- If keys of the specified algorithm are unsupported.java.security.InvalidKeyException
- If the given wrapped key is invalid.protected byte[] engineWrap(java.security.Key key) throws java.security.InvalidKeyException, javax.crypto.IllegalBlockSizeException
pkcs11
instead of engine
.engineWrap
in class javax.crypto.CipherSpi
key
- The key to wrap (encrypt).java.security.InvalidKeyException
- If the given key is invalid.javax.crypto.IllegalBlockSizeException
- If the key cannot be wrapper due to block size restriction of the wrapping cipher.protected byte[] pkcs11Wrap(java.security.Key key) throws java.security.InvalidKeyException, javax.crypto.IllegalBlockSizeException
key
- The key to wrap (encrypt).java.security.InvalidKeyException
- If the given key is invalid.javax.crypto.IllegalBlockSizeException
- If the key cannot be wrapper due to block size restriction of the wrapping cipher.protected abstract iaik.pkcs.pkcs11.Mechanism getDefaultMechanism()
protected abstract iaik.pkcs.pkcs11.Mechanism getMechanism()
protected void finalize() throws java.lang.Throwable
finalize
in class java.lang.Object
java.lang.Throwable
- If finalization fails.IAIK JavaSecurity Website https://jce.iaik.tugraz.at/
IAIK at Graz University of Technology, Austria, Europe
Copyright 2001-2023 IAIK, Graz University of Technology, Inffeldgasse 16a, 8010 Graz, Austria. All Rights Reserved. Version 1.9.4