GordianSkeinMac.java
/*
* GordianKnot: Security Suite
* Copyright 2012-2026. Tony Washer
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.github.tonywasher.joceanus.gordianknot.impl.ext.macs;
import io.github.tonywasher.joceanus.gordianknot.impl.ext.digests.GordianSkeinBase;
import io.github.tonywasher.joceanus.gordianknot.impl.ext.params.GordianSkeinParameters;
import io.github.tonywasher.joceanus.gordianknot.impl.ext.params.GordianSkeinParameters.GordianSkeinParametersBuilder;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.engines.ThreefishEngine;
import org.bouncycastle.crypto.params.KeyParameter;
/**
* Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes,
* based on the {@link ThreefishEngine Threefish} tweakable block cipher.
* <p>
* This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
* competition in October 2010.
* <p>
* Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
* Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
*
* @see GordianSkeinBase
* @see GordianSkeinParameters
*/
public class GordianSkeinMac
implements Mac {
/**
* 256 bit block size - Skein MAC-256.
*/
public static final int SKEIN_256 = GordianSkeinBase.SKEIN_256;
/**
* 512 bit block size - Skein MAC-512.
*/
public static final int SKEIN_512 = GordianSkeinBase.SKEIN_512;
/**
* 1024 bit block size - Skein MAC-1024.
*/
public static final int SKEIN_1024 = GordianSkeinBase.SKEIN_1024;
/**
* The engine.
*/
private final GordianSkeinBase theEngine;
/**
* Constructs a Skein MAC with an internal state size and output size.
*
* @param stateSizeBits the internal state size in bits - one of {@link #SKEIN_256}, {@link #SKEIN_512} or
* {@link #SKEIN_1024}.
* @param digestSizeBits the output/MAC size to produce in bits, which must be an integral number of bytes.
*/
public GordianSkeinMac(final int stateSizeBits,
final int digestSizeBits) {
this.theEngine = new GordianSkeinBase(stateSizeBits, digestSizeBits);
}
/**
* Copy constructor.
*
* @param mac the source mac
*/
public GordianSkeinMac(final GordianSkeinMac mac) {
this.theEngine = new GordianSkeinBase(mac.theEngine);
}
/**
* Obtain the lgorithm name.
*
* @return the name
*/
public String getAlgorithmName() {
return "Skein-MAC-" + (theEngine.getBlockSize() * Byte.SIZE) + "-" + (theEngine.getOutputSize() * Byte.SIZE);
}
/**
* Initialises the Skein digest with the provided parameters.<br>
* See {@link GordianSkeinParameters} for details on the parameterisation of the Skein hash function.
*
* @param params an instance of {@link GordianSkeinParameters} or {@link KeyParameter}.
*/
public void init(final CipherParameters params)
throws IllegalArgumentException {
final GordianSkeinParameters skeinParameters;
if (params instanceof GordianSkeinParameters) {
skeinParameters = (GordianSkeinParameters) params;
} else if (params instanceof KeyParameter) {
skeinParameters = new GordianSkeinParametersBuilder().setKey(((KeyParameter) params).getKey()).build();
} else {
throw new IllegalArgumentException("Invalid parameter passed to Skein MAC init - "
+ params.getClass().getName());
}
if (skeinParameters.getKey() == null) {
throw new IllegalArgumentException("Skein MAC requires a key parameter.");
}
theEngine.init(skeinParameters);
}
@Override
public int getMacSize() {
return theEngine.getOutputSize();
}
@Override
public void reset() {
theEngine.reset();
}
@Override
public void update(final byte in) {
theEngine.update(in);
}
@Override
public void update(final byte[] in,
final int inOff,
final int len) {
theEngine.update(in, inOff, len);
}
@Override
public int doFinal(final byte[] out,
final int outOff) {
return theEngine.doFinal(out, outOff);
}
}