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.GordianLength;
20  
21  import java.util.Objects;
22  
23  /**
24   * The SymCipherSpec class.
25   */
26  public class GordianSymCipherSpec
27          extends GordianCipherSpec<GordianSymKeySpec> {
28      /**
29       * The IV length.
30       */
31      public static final int AADIVLEN = 12;
32  
33      /**
34       * The Separator.
35       */
36      private static final String SEP = "-";
37  
38      /**
39       * Cipher Mode.
40       */
41      private final GordianCipherMode theMode;
42  
43      /**
44       * Cipher Padding.
45       */
46      private final GordianPadding thePadding;
47  
48      /**
49       * The Validity.
50       */
51      private final boolean isValid;
52  
53      /**
54       * The String name.
55       */
56      private String theName;
57  
58      /**
59       * Constructor.
60       *
61       * @param pKeySpec the keySpec
62       * @param pMode    the mode
63       * @param pPadding the padding
64       */
65      public GordianSymCipherSpec(final GordianSymKeySpec pKeySpec,
66                                  final GordianCipherMode pMode,
67                                  final GordianPadding pPadding) {
68          super(pKeySpec);
69          theMode = pMode;
70          thePadding = pPadding;
71          isValid = checkValidity();
72      }
73  
74      /**
75       * Obtain the cipherMode.
76       *
77       * @return the mode
78       */
79      public GordianCipherMode getCipherMode() {
80          return theMode;
81      }
82  
83      /**
84       * Obtain the padding.
85       *
86       * @return the padding
87       */
88      public GordianPadding getPadding() {
89          return thePadding;
90      }
91  
92      @Override
93      public boolean isValid() {
94          return isValid;
95      }
96  
97      @Override
98      public boolean needsIV() {
99          return theMode.needsIV();
100     }
101 
102     /**
103      * Obtain the blockLength.
104      *
105      * @return the blockLength
106      */
107     public GordianLength getBlockLength() {
108         return getKeyType().getBlockLength();
109     }
110 
111     @Override
112     public int getIVLength() {
113         if (getCipherMode().isAAD()) {
114             return AADIVLEN;
115         }
116         final int myBlockLen = getKeyType().getBlockLength().getByteLength();
117         return GordianCipherMode.G3413CTR.equals(theMode)
118                 ? myBlockLen >> 1
119                 : myBlockLen;
120     }
121 
122     /**
123      * Is this an AAD mode?
124      *
125      * @return true/false
126      */
127     public boolean isAAD() {
128         return theMode != null && theMode.isAAD();
129     }
130 
131     @Override
132     public String toString() {
133         /* If we have not yet loaded the name */
134         if (theName == null) {
135             /* If the keySpec is valid */
136             if (isValid) {
137                 /* Load the name */
138                 theName = super.toString();
139                 theName += SEP + theMode;
140                 if (!GordianPadding.NONE.equals(thePadding)) {
141                     theName += SEP + thePadding;
142                 }
143             } else {
144                 /* Report invalid spec */
145                 theName = "InvalidSymCipherSpec: " + super.toString() + ":" + theMode + ":" + thePadding;
146             }
147         }
148 
149         /* return the name */
150         return theName;
151     }
152 
153     /**
154      * Check spec validity.
155      *
156      * @return valid true/false
157      */
158     private boolean checkValidity() {
159         final GordianSymKeySpec mySpec = getKeyType();
160         return mySpec != null && mySpec.isValid()
161                 && theMode != null && thePadding != null;
162     }
163 
164     @Override
165     public boolean equals(final Object pThat) {
166         /* Handle the trivial cases */
167         if (this == pThat) {
168             return true;
169         }
170         if (pThat == null) {
171             return false;
172         }
173 
174         /* Check KeyType, Mode and padding */
175         return pThat instanceof GordianSymCipherSpec myThat
176                 && getKeyType().equals(myThat.getKeyType())
177                 && theMode == myThat.getCipherMode()
178                 && thePadding == myThat.getPadding();
179     }
180 
181     @Override
182     public int hashCode() {
183         return Objects.hash(getKeyType(), theMode, thePadding);
184     }
185 }