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.GordianException;
20
21 import java.util.Arrays;
22
23 /**
24 * GordianKnot base for Cipher.
25 */
26 public interface GordianCipher {
27 /**
28 * Determine the maximum number of output bytes that will be produced for the given number of
29 * input bytes.
30 *
31 * @param pLength the number of input bytes
32 * @return # of output bytes
33 */
34 int getOutputLength(int pLength);
35
36 /**
37 * Process the passed data and return intermediate results.
38 *
39 * @param pBytes Bytes to update cipher with
40 * @return the intermediate processed data
41 * @throws GordianException on error
42 */
43 default byte[] update(final byte[] pBytes) throws GordianException {
44 return update(pBytes, 0, pBytes == null ? 0 : pBytes.length);
45 }
46
47 /**
48 * Process the passed data and return intermediate results.
49 *
50 * @param pBytes Bytes to update cipher with
51 * @param pOffset offset within pBytes to read bytes from
52 * @param pLength length of data to update with
53 * @return the intermediate processed data
54 * @throws GordianException on error
55 */
56 default byte[] update(final byte[] pBytes,
57 final int pOffset,
58 final int pLength) throws GordianException {
59 /* Create output buffer */
60 final int myLen = getOutputLength(pLength);
61 final byte[] myOutput = new byte[myLen];
62
63 /* Process the data */
64 final int myOut = update(pBytes, pOffset, pLength, myOutput, 0);
65
66 /* Return full buffer if possible */
67 if (myOut == myLen) {
68 return myOutput;
69 }
70
71 /* Cut down buffer */
72 final byte[] myReturn = Arrays.copyOf(myOutput, myOut);
73 Arrays.fill(myOutput, (byte) 0);
74 return myReturn;
75 }
76
77 /**
78 * Process the passed data and return intermediate results.
79 *
80 * @param pBytes Bytes to update cipher with
81 * @param pOffset offset within pBytes to read bytes from
82 * @param pLength length of data to update with
83 * @param pOutput the output buffer to receive processed data
84 * @return the number of bytes transferred to the output buffer
85 * @throws GordianException on error
86 */
87 default int update(final byte[] pBytes,
88 final int pOffset,
89 final int pLength,
90 final byte[] pOutput) throws GordianException {
91 return update(pBytes, pOffset, pLength, pOutput, 0);
92 }
93
94 /**
95 * Process the passed data and return intermediate results.
96 *
97 * @param pBytes Bytes to update cipher with
98 * @param pOffset offset within pBytes to read bytes from
99 * @param pLength length of data to update with
100 * @param pOutput the output buffer to receive processed data
101 * @param pOutOffset offset within pOutput to write bytes to
102 * @return the number of bytes transferred to the output buffer
103 * @throws GordianException on error
104 */
105 int update(byte[] pBytes,
106 int pOffset,
107 int pLength,
108 byte[] pOutput,
109 int pOutOffset) throws GordianException;
110
111 /**
112 * Complete the Cipher operation and return final results.
113 *
114 * @return the remaining processed data
115 * @throws GordianException on error
116 */
117 default byte[] finish() throws GordianException {
118 /* Create output buffer */
119 final int myLen = getOutputLength(0);
120 final byte[] myOutput = new byte[myLen];
121
122 /* Process the data */
123 final int myOut = finish(myOutput, 0);
124
125 /* Return full buffer if possible */
126 if (myOut == myLen) {
127 return myOutput;
128 }
129
130 /* Cut down buffer */
131 final byte[] myReturn = Arrays.copyOf(myOutput, myOut);
132 Arrays.fill(myOutput, (byte) 0);
133 return myReturn;
134 }
135
136 /**
137 * Process the passed data and return final results.
138 *
139 * @param pBytes Bytes to update cipher with
140 * @return the remaining processed data
141 * @throws GordianException on error
142 */
143 default byte[] finish(final byte[] pBytes) throws GordianException {
144 return finish(pBytes, 0, pBytes == null ? 0 : pBytes.length);
145 }
146
147 /**
148 * Process the passed data and return final results.
149 *
150 * @param pBytes Bytes to update cipher with
151 * @param pOffset offset within pBytes to read bytes from
152 * @param pLength length of data to update with
153 * @return the remaining processed data
154 * @throws GordianException on error
155 */
156 default byte[] finish(final byte[] pBytes,
157 final int pOffset,
158 final int pLength) throws GordianException {
159 /* Create output buffer */
160 final int myLen = getOutputLength(pLength);
161 final byte[] myOutput = new byte[myLen];
162
163 /* Process the data */
164 final int myOut = finish(pBytes, pOffset, pLength, myOutput, 0);
165
166 /* Return full buffer if possible */
167 if (myOut == myLen) {
168 return myOutput;
169 }
170
171 /* Cut down buffer */
172 final byte[] myReturn = Arrays.copyOf(myOutput, myOut);
173 Arrays.fill(myOutput, (byte) 0);
174 return myReturn;
175 }
176
177 /**
178 * Process the passed data and return final results.
179 *
180 * @param pBytes Bytes to update cipher with
181 * @param pOffset offset within pBytes to read bytes from
182 * @param pLength length of data to update with
183 * @param pOutput the output buffer to receive processed data
184 * @return the number of bytes transferred to the output buffer
185 * @throws GordianException on error
186 */
187 default int finish(final byte[] pBytes,
188 final int pOffset,
189 final int pLength,
190 final byte[] pOutput) throws GordianException {
191 return finish(pBytes, pOffset, pLength, pOutput, 0);
192 }
193
194 /**
195 * Process the passed data and return final results.
196 *
197 * @param pBytes Bytes to update cipher with
198 * @param pOffset offset within pBytes to read bytes from
199 * @param pLength length of data to update with
200 * @param pOutput the output buffer to receive processed data
201 * @param pOutOffset offset within pOutput to write bytes to
202 * @return the number of bytes transferred to the output buffer
203 * @throws GordianException on error
204 */
205 default int finish(final byte[] pBytes,
206 final int pOffset,
207 final int pLength,
208 final byte[] pOutput,
209 final int pOutOffset) throws GordianException {
210 /* Update the data */
211 final int myLen = update(pBytes, pOffset, pLength, pOutput, pOutOffset);
212
213 /* Complete the operation */
214 return myLen + finish(pOutput, pOutOffset + myLen);
215 }
216
217 /**
218 * Complete the Cipher operation and return final results.
219 *
220 * @param pOutput the output buffer to receive processed data
221 * @param pOutOffset offset within pOutput to write bytes to
222 * @return the number of bytes transferred to the output buffer
223 * @throws GordianException on error
224 */
225 int finish(byte[] pOutput,
226 int pOutOffset) throws GordianException;
227 }