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.digests.GordianSkeinXof;
21  import io.github.tonywasher.joceanus.gordianknot.impl.ext.params.GordianSkeinParameters;
22  import io.github.tonywasher.joceanus.gordianknot.impl.ext.params.GordianSkeinParameters.GordianSkeinParametersBuilder;
23  import org.bouncycastle.crypto.CipherParameters;
24  import org.bouncycastle.crypto.Mac;
25  import org.bouncycastle.crypto.Xof;
26  import org.bouncycastle.crypto.engines.ThreefishEngine;
27  import org.bouncycastle.crypto.params.KeyParameter;
28  
29  /**
30   * Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes,
31   * based on the {@link ThreefishEngine Threefish} tweakable block cipher.
32   * <p>
33   * This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
34   * competition in October 2010.
35   * <p>
36   * Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
37   * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
38   *
39   * @see GordianSkeinBase
40   * @see GordianSkeinParameters
41   */
42  public class GordianSkeinXMac
43          implements Mac, Xof {
44      /**
45       * 256 bit block size - Skein MAC-256.
46       */
47      public static final int SKEIN_256 = GordianSkeinBase.SKEIN_256;
48  
49      /**
50       * 512 bit block size - Skein MAC-512.
51       */
52      public static final int SKEIN_512 = GordianSkeinBase.SKEIN_512;
53  
54      /**
55       * 1024 bit block size - Skein MAC-1024.
56       */
57      public static final int SKEIN_1024 = GordianSkeinBase.SKEIN_1024;
58  
59      /**
60       * The engine.
61       */
62      private final GordianSkeinBase theEngine;
63  
64      /**
65       * The Xof.
66       */
67      private final GordianSkeinXof theXof;
68  
69      /**
70       * Constructs a Skein MAC with an internal state size and output size.
71       *
72       * @param stateSizeBits the internal state size in bits - one of {@link #SKEIN_256}, {@link #SKEIN_512} or
73       *                      {@link #SKEIN_1024}.
74       */
75      public GordianSkeinXMac(final int stateSizeBits) {
76          this.theEngine = new GordianSkeinBase(stateSizeBits, stateSizeBits);
77          this.theXof = new GordianSkeinXof(theEngine);
78      }
79  
80      /**
81       * Copy constructor.
82       *
83       * @param mac the source mac
84       */
85      public GordianSkeinXMac(final GordianSkeinXMac mac) {
86          this.theEngine = new GordianSkeinBase(mac.theEngine);
87          this.theXof = new GordianSkeinXof(theEngine);
88      }
89  
90      /**
91       * Obtain the lgorithm name.
92       *
93       * @return the name
94       */
95      public String getAlgorithmName() {
96          return "SkeinX-MAC-" + (theEngine.getBlockSize() * Byte.SIZE);
97      }
98  
99      /**
100      * Initialises the Skein digest with the provided parameters.<br>
101      * See {@link GordianSkeinParameters} for details on the parameterisation of the Skein hash function.
102      *
103      * @param params an instance of {@link GordianSkeinParameters} or {@link KeyParameter}.
104      */
105     public void init(final CipherParameters params)
106             throws IllegalArgumentException {
107         final GordianSkeinParameters skeinParameters;
108         if (params instanceof GordianSkeinParameters) {
109             skeinParameters = (GordianSkeinParameters) params;
110         } else if (params instanceof KeyParameter) {
111             skeinParameters = new GordianSkeinParametersBuilder().setKey(((KeyParameter) params).getKey()).build();
112         } else {
113             throw new IllegalArgumentException("Invalid parameter passed to Skein MAC init - "
114                     + params.getClass().getName());
115         }
116         if (skeinParameters.getKey() == null) {
117             throw new IllegalArgumentException("Skein MAC requires a key parameter.");
118         }
119         theEngine.init(skeinParameters);
120     }
121 
122     @Override
123     public int getMacSize() {
124         return theEngine.getOutputSize();
125     }
126 
127     @Override
128     public void reset() {
129         theXof.reset();
130     }
131 
132     @Override
133     public void update(final byte in) {
134         theXof.update(in);
135     }
136 
137     @Override
138     public void update(final byte[] in,
139                        final int inOff,
140                        final int len) {
141         theXof.update(in, inOff, len);
142     }
143 
144     @Override
145     public int doFinal(final byte[] out,
146                        final int outOff) {
147         return theXof.doFinal(out, outOff);
148     }
149 
150     @Override
151     public int doFinal(final byte[] out, final int outOff, final int outLen) {
152         return theXof.doFinal(out, outOff, outLen);
153     }
154 
155     @Override
156     public int doOutput(final byte[] out, final int outOff, final int outLen) {
157         return theXof.doOutput(out, outOff, outLen);
158     }
159 
160     @Override
161     public int getByteLength() {
162         return theXof.getByteLength();
163     }
164 
165     @Override
166     public int getDigestSize() {
167         return theXof.getDigestSize();
168     }
169 }