1 /*
2 * GordianKnot: Security Suite
3 * Copyright 2012-2026. Tony Washer
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 * use this file except in compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17 package io.github.tonywasher.joceanus.gordianknot.impl.ext.macs;
18
19 import io.github.tonywasher.joceanus.gordianknot.impl.ext.digests.GordianSkeinBase;
20 import io.github.tonywasher.joceanus.gordianknot.impl.ext.params.GordianSkeinParameters;
21 import io.github.tonywasher.joceanus.gordianknot.impl.ext.params.GordianSkeinParameters.GordianSkeinParametersBuilder;
22 import org.bouncycastle.crypto.CipherParameters;
23 import org.bouncycastle.crypto.Mac;
24 import org.bouncycastle.crypto.engines.ThreefishEngine;
25 import org.bouncycastle.crypto.params.KeyParameter;
26
27 /**
28 * Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes,
29 * based on the {@link ThreefishEngine Threefish} tweakable block cipher.
30 * <p>
31 * This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
32 * competition in October 2010.
33 * <p>
34 * Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
35 * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
36 *
37 * @see GordianSkeinBase
38 * @see GordianSkeinParameters
39 */
40 public class GordianSkeinMac
41 implements Mac {
42 /**
43 * 256 bit block size - Skein MAC-256.
44 */
45 public static final int SKEIN_256 = GordianSkeinBase.SKEIN_256;
46
47 /**
48 * 512 bit block size - Skein MAC-512.
49 */
50 public static final int SKEIN_512 = GordianSkeinBase.SKEIN_512;
51
52 /**
53 * 1024 bit block size - Skein MAC-1024.
54 */
55 public static final int SKEIN_1024 = GordianSkeinBase.SKEIN_1024;
56
57 /**
58 * The engine.
59 */
60 private final GordianSkeinBase theEngine;
61
62 /**
63 * Constructs a Skein MAC with an internal state size and output size.
64 *
65 * @param stateSizeBits the internal state size in bits - one of {@link #SKEIN_256}, {@link #SKEIN_512} or
66 * {@link #SKEIN_1024}.
67 * @param digestSizeBits the output/MAC size to produce in bits, which must be an integral number of bytes.
68 */
69 public GordianSkeinMac(final int stateSizeBits,
70 final int digestSizeBits) {
71 this.theEngine = new GordianSkeinBase(stateSizeBits, digestSizeBits);
72 }
73
74 /**
75 * Copy constructor.
76 *
77 * @param mac the source mac
78 */
79 public GordianSkeinMac(final GordianSkeinMac mac) {
80 this.theEngine = new GordianSkeinBase(mac.theEngine);
81 }
82
83 /**
84 * Obtain the lgorithm name.
85 *
86 * @return the name
87 */
88 public String getAlgorithmName() {
89 return "Skein-MAC-" + (theEngine.getBlockSize() * Byte.SIZE) + "-" + (theEngine.getOutputSize() * Byte.SIZE);
90 }
91
92 /**
93 * Initialises the Skein digest with the provided parameters.<br>
94 * See {@link GordianSkeinParameters} for details on the parameterisation of the Skein hash function.
95 *
96 * @param params an instance of {@link GordianSkeinParameters} or {@link KeyParameter}.
97 */
98 public void init(final CipherParameters params)
99 throws IllegalArgumentException {
100 final GordianSkeinParameters skeinParameters;
101 if (params instanceof GordianSkeinParameters) {
102 skeinParameters = (GordianSkeinParameters) params;
103 } else if (params instanceof KeyParameter) {
104 skeinParameters = new GordianSkeinParametersBuilder().setKey(((KeyParameter) params).getKey()).build();
105 } else {
106 throw new IllegalArgumentException("Invalid parameter passed to Skein MAC init - "
107 + params.getClass().getName());
108 }
109 if (skeinParameters.getKey() == null) {
110 throw new IllegalArgumentException("Skein MAC requires a key parameter.");
111 }
112 theEngine.init(skeinParameters);
113 }
114
115 @Override
116 public int getMacSize() {
117 return theEngine.getOutputSize();
118 }
119
120 @Override
121 public void reset() {
122 theEngine.reset();
123 }
124
125 @Override
126 public void update(final byte in) {
127 theEngine.update(in);
128 }
129
130 @Override
131 public void update(final byte[] in,
132 final int inOff,
133 final int len) {
134 theEngine.update(in, inOff, len);
135 }
136
137 @Override
138 public int doFinal(final byte[] out,
139 final int outOff) {
140 return theEngine.doFinal(out, outOff);
141 }
142 }