View Javadoc
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 }