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.api.cipher;
18  
19  import io.github.tonywasher.joceanus.gordianknot.api.base.GordianKeySpec;
20  import io.github.tonywasher.joceanus.gordianknot.api.base.GordianLength;
21  
22  import java.util.Objects;
23  
24  /**
25   * SymKey specification.
26   */
27  public class GordianSymKeySpec
28          implements GordianKeySpec {
29      /**
30       * The Separator.
31       */
32      private static final String SEP = "-";
33  
34      /**
35       * The SymKey Type.
36       */
37      private final GordianSymKeyType theSymKeyType;
38  
39      /**
40       * The Engine Block Length.
41       */
42      private final GordianLength theBlockLength;
43  
44      /**
45       * The Key Length.
46       */
47      private final GordianLength theKeyLength;
48  
49      /**
50       * The Validity.
51       */
52      private final boolean isValid;
53  
54      /**
55       * The String name.
56       */
57      private String theName;
58  
59      /**
60       * Constructor.
61       *
62       * @param pSymKeyType the symKeyType
63       * @param pKeyLength  the keyLength
64       */
65      public GordianSymKeySpec(final GordianSymKeyType pSymKeyType,
66                               final GordianLength pKeyLength) {
67          this(pSymKeyType, pSymKeyType.getDefaultBlockLength(), pKeyLength);
68      }
69  
70      /**
71       * Constructor.
72       *
73       * @param pSymKeyType  the symKeyType
74       * @param pBlockLength the stateLength
75       * @param pKeyLength   the keyLength
76       */
77      public GordianSymKeySpec(final GordianSymKeyType pSymKeyType,
78                               final GordianLength pBlockLength,
79                               final GordianLength pKeyLength) {
80          /* Store parameters */
81          theSymKeyType = pSymKeyType;
82          theBlockLength = pBlockLength;
83          theKeyLength = pKeyLength;
84          isValid = checkValidity();
85      }
86  
87      /**
88       * Obtain symKey Type.
89       *
90       * @return the symKeyType
91       */
92      public GordianSymKeyType getSymKeyType() {
93          return theSymKeyType;
94      }
95  
96      /**
97       * Obtain Block Length.
98       *
99       * @return the blockLength
100      */
101     public GordianLength getBlockLength() {
102         return theBlockLength;
103     }
104 
105     @Override
106     public GordianLength getKeyLength() {
107         return theKeyLength;
108     }
109 
110     /**
111      * Obtain HalfBlock length.
112      *
113      * @return the Length
114      */
115     public GordianLength getHalfBlockLength() {
116         switch (theBlockLength) {
117             case LEN_64:
118                 return GordianLength.LEN_32;
119             case LEN_128:
120                 return GordianLength.LEN_64;
121             case LEN_256:
122                 return GordianLength.LEN_128;
123             case LEN_512:
124                 return GordianLength.LEN_256;
125             case LEN_1024:
126                 return GordianLength.LEN_512;
127             default:
128                 return theBlockLength;
129         }
130     }
131 
132     /**
133      * Is the keySpec valid?
134      *
135      * @return true/false.
136      */
137     public boolean isValid() {
138         return isValid;
139     }
140 
141     /**
142      * Check spec validity.
143      *
144      * @return valid true/false
145      */
146     private boolean checkValidity() {
147         /* Everything must be non-null */
148         if (theSymKeyType == null
149                 || theBlockLength == null
150                 || theKeyLength == null) {
151             return false;
152         }
153 
154         /* Check blockLength and keyLength validity */
155         return theSymKeyType.validBlockAndKeyLengths(theBlockLength, theKeyLength);
156     }
157 
158     @Override
159     public String toString() {
160         /* If we have not yet loaded the name */
161         if (theName == null) {
162             /* If the keySpec is valid */
163             if (isValid) {
164                 /* Load the name */
165                 theName = theSymKeyType.toString();
166                 if (theSymKeyType.hasMultipleBlockLengths()
167                         && !GordianSymKeyType.THREEFISH.equals(theSymKeyType)) {
168                     int myLen = theBlockLength.getLength();
169                     if (GordianSymKeyType.RC5.equals(theSymKeyType)) {
170                         myLen >>= 1;
171                     }
172                     theName += myLen;
173                 }
174                 theName += SEP + theKeyLength;
175             } else {
176                 /* Report invalid spec */
177                 theName = "InvalidSymKeySpec: " + theSymKeyType + ":" + theBlockLength + ":" + theKeyLength;
178             }
179         }
180 
181         /* return the name */
182         return theName;
183     }
184 
185     @Override
186     public boolean equals(final Object pThat) {
187         /* Handle the trivial cases */
188         if (this == pThat) {
189             return true;
190         }
191         if (pThat == null) {
192             return false;
193         }
194 
195         /* Check subFields */
196         return pThat instanceof GordianSymKeySpec myThat
197                 && theSymKeyType == myThat.getSymKeyType()
198                 && theBlockLength == myThat.getBlockLength()
199                 && theKeyLength == myThat.getKeyLength();
200     }
201 
202     @Override
203     public int hashCode() {
204         return Objects.hash(theSymKeyType, theBlockLength, theKeyLength);
205     }
206 }