@@ -141,46 +141,48 @@ public byte[] Decrypt(ArraySegment<byte> ciphertext, ArraySegment<byte> addition
141141 }
142142 }
143143
144- public int GetEncryptedSize ( int plainTextLength )
145- {
146- // A buffer to hold the key modifier, nonce, encrypted data, and tag.
147- // In GCM, the encrypted output will be the same length as the plaintext input.
148- return checked ( ( int ) ( KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + plainTextLength + TAG_SIZE_IN_BYTES ) ) ;
149- }
150-
151- public bool TryEncrypt ( ReadOnlySpan < byte > plaintext , ReadOnlySpan < byte > additionalAuthenticatedData , Span < byte > destination , out int bytesWritten )
144+ public byte [ ] Encrypt ( ArraySegment < byte > plaintext , ArraySegment < byte > additionalAuthenticatedData , uint preBufferSize , uint postBufferSize )
152145 {
153- bytesWritten = 0 ;
146+ plaintext . Validate ( ) ;
147+ additionalAuthenticatedData . Validate ( ) ;
154148
155149 try
156150 {
157- // Generate random key modifier and nonce
151+ // Allocate a buffer to hold the key modifier, nonce, encrypted data, and tag.
152+ // In GCM, the encrypted output will be the same length as the plaintext input.
153+ var retVal = new byte [ checked ( preBufferSize + KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + plaintext . Count + TAG_SIZE_IN_BYTES + postBufferSize ) ] ;
154+ int keyModifierOffset ; // position in ciphertext.Array where key modifier begins
155+ int nonceOffset ; // position in ciphertext.Array where key modifier ends / nonce begins
156+ int encryptedDataOffset ; // position in ciphertext.Array where nonce ends / encryptedData begins
157+ int tagOffset ; // position in ciphertext.Array where encrypted data ends
158+
159+ checked
160+ {
161+ keyModifierOffset = plaintext . Offset + ( int ) preBufferSize ;
162+ nonceOffset = keyModifierOffset + KEY_MODIFIER_SIZE_IN_BYTES ;
163+ encryptedDataOffset = nonceOffset + NONCE_SIZE_IN_BYTES ;
164+ tagOffset = encryptedDataOffset + plaintext . Count ;
165+ }
166+
167+ // Randomly generate the key modifier and nonce
158168 var keyModifier = _genRandom . GenRandom ( KEY_MODIFIER_SIZE_IN_BYTES ) ;
159169 var nonceBytes = _genRandom . GenRandom ( NONCE_SIZE_IN_BYTES ) ;
160170
161- // KeyModifier and nonce to destination
162- keyModifier . CopyTo ( destination . Slice ( bytesWritten , KEY_MODIFIER_SIZE_IN_BYTES ) ) ;
163- bytesWritten += KEY_MODIFIER_SIZE_IN_BYTES ;
164- nonceBytes . CopyTo ( destination . Slice ( bytesWritten , NONCE_SIZE_IN_BYTES ) ) ;
165- bytesWritten += NONCE_SIZE_IN_BYTES ;
171+ Buffer . BlockCopy ( keyModifier , 0 , retVal , ( int ) preBufferSize , keyModifier . Length ) ;
172+ Buffer . BlockCopy ( nonceBytes , 0 , retVal , ( int ) preBufferSize + keyModifier . Length , nonceBytes . Length ) ;
166173
167- // At this point, destination := { keyModifier | nonce | _____ | _____ }
174+ // At this point, retVal := { preBuffer | keyModifier | nonce | _____ | _____ | postBuffer }
168175
169176 // Use the KDF to generate a new symmetric block cipher key
170177 // We'll need a temporary buffer to hold the symmetric encryption subkey
171- Span < byte > decryptedKdk = _keyDerivationKey . Length <= 256
172- ? stackalloc byte [ 256 ] . Slice ( 0 , _keyDerivationKey . Length )
173- : new byte [ _keyDerivationKey . Length ] ;
174- var derivedKey = _derivedkeySizeInBytes <= 256
175- ? stackalloc byte [ 256 ] . Slice ( 0 , _derivedkeySizeInBytes )
176- : new byte [ _derivedkeySizeInBytes ] ;
177-
178- fixed ( byte * decryptedKdkUnsafe = decryptedKdk )
178+ var decryptedKdk = new byte [ _keyDerivationKey . Length ] ;
179+ var derivedKey = new byte [ _derivedkeySizeInBytes ] ;
180+ fixed ( byte * __unused__1 = decryptedKdk )
179181 fixed ( byte * __unused__2 = derivedKey )
180182 {
181183 try
182184 {
183- _keyDerivationKey . WriteSecretIntoBuffer ( decryptedKdkUnsafe , decryptedKdk . Length ) ;
185+ _keyDerivationKey . WriteSecretIntoBuffer ( new ArraySegment < byte > ( decryptedKdk ) ) ;
184186 ManagedSP800_108_CTR_HMACSHA512 . DeriveKeys (
185187 kdk : decryptedKdk ,
186188 label : additionalAuthenticatedData ,
@@ -189,25 +191,22 @@ public bool TryEncrypt(ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> addition
189191 operationSubkey : derivedKey ,
190192 validationSubkey : Span < byte > . Empty /* filling in derivedKey only */ ) ;
191193
192- // Perform GCM encryption. Destination buffer expected structure:
193- // { keyModifier | nonce | encryptedData | authenticationTag }
194- var nonce = destination . Slice ( KEY_MODIFIER_SIZE_IN_BYTES , NONCE_SIZE_IN_BYTES ) ;
195- var encrypted = destination . Slice ( bytesWritten , plaintext . Length ) ;
196- var tag = destination . Slice ( bytesWritten + plaintext . Length , TAG_SIZE_IN_BYTES ) ;
197-
194+ // do gcm
195+ var nonce = new Span < byte > ( retVal , nonceOffset , NONCE_SIZE_IN_BYTES ) ;
196+ var tag = new Span < byte > ( retVal , tagOffset , TAG_SIZE_IN_BYTES ) ;
197+ var encrypted = new Span < byte > ( retVal , encryptedDataOffset , plaintext . Count ) ;
198198 using var aes = new AesGcm ( derivedKey , TAG_SIZE_IN_BYTES ) ;
199199 aes . Encrypt ( nonce , plaintext , encrypted , tag ) ;
200200
201- // At this point, destination := { keyModifier | nonce | encryptedData | authenticationTag }
201+ // At this point, retVal := { preBuffer | keyModifier | nonce | encryptedData | authenticationTag | postBuffer }
202202 // And we're done!
203- bytesWritten += plaintext . Length + TAG_SIZE_IN_BYTES ;
204- return true ;
203+ return retVal ;
205204 }
206205 finally
207206 {
208207 // delete since these contain secret material
209- decryptedKdk . Clear ( ) ;
210- derivedKey . Clear ( ) ;
208+ Array . Clear ( decryptedKdk , 0 , decryptedKdk . Length ) ;
209+ Array . Clear ( derivedKey , 0 , derivedKey . Length ) ;
211210 }
212211 }
213212 }
@@ -218,48 +217,50 @@ public bool TryEncrypt(ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> addition
218217 }
219218 }
220219
221- public byte [ ] Encrypt ( ArraySegment < byte > plaintext , ArraySegment < byte > additionalAuthenticatedData , uint preBufferSize , uint postBufferSize )
220+ public byte [ ] Encrypt ( ArraySegment < byte > plaintext , ArraySegment < byte > additionalAuthenticatedData )
221+ => Encrypt ( plaintext , additionalAuthenticatedData , 0 , 0 ) ;
222+
223+ #if NET10_0_OR_GREATER
224+ public int GetEncryptedSize ( int plainTextLength )
222225 {
223- plaintext . Validate ( ) ;
224- additionalAuthenticatedData . Validate ( ) ;
226+ // A buffer to hold the key modifier, nonce, encrypted data, and tag.
227+ // In GCM, the encrypted output will be the same length as the plaintext input.
228+ return checked ( ( int ) ( KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + plainTextLength + TAG_SIZE_IN_BYTES ) ) ;
229+ }
230+
231+ public bool TryEncrypt ( ReadOnlySpan < byte > plaintext , ReadOnlySpan < byte > additionalAuthenticatedData , Span < byte > destination , out int bytesWritten )
232+ {
233+ bytesWritten = 0 ;
225234
226235 try
227236 {
228- // Allocate a buffer to hold the key modifier, nonce, encrypted data, and tag.
229- // In GCM, the encrypted output will be the same length as the plaintext input.
230- var retVal = new byte [ checked ( preBufferSize + KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + plaintext . Count + TAG_SIZE_IN_BYTES + postBufferSize ) ] ;
231- int keyModifierOffset ; // position in ciphertext.Array where key modifier begins
232- int nonceOffset ; // position in ciphertext.Array where key modifier ends / nonce begins
233- int encryptedDataOffset ; // position in ciphertext.Array where nonce ends / encryptedData begins
234- int tagOffset ; // position in ciphertext.Array where encrypted data ends
235-
236- checked
237- {
238- keyModifierOffset = plaintext . Offset + ( int ) preBufferSize ;
239- nonceOffset = keyModifierOffset + KEY_MODIFIER_SIZE_IN_BYTES ;
240- encryptedDataOffset = nonceOffset + NONCE_SIZE_IN_BYTES ;
241- tagOffset = encryptedDataOffset + plaintext . Count ;
242- }
243-
244- // Randomly generate the key modifier and nonce
237+ // Generate random key modifier and nonce
245238 var keyModifier = _genRandom . GenRandom ( KEY_MODIFIER_SIZE_IN_BYTES ) ;
246239 var nonceBytes = _genRandom . GenRandom ( NONCE_SIZE_IN_BYTES ) ;
247240
248- Buffer . BlockCopy ( keyModifier , 0 , retVal , ( int ) preBufferSize , keyModifier . Length ) ;
249- Buffer . BlockCopy ( nonceBytes , 0 , retVal , ( int ) preBufferSize + keyModifier . Length , nonceBytes . Length ) ;
241+ // KeyModifier and nonce to destination
242+ keyModifier . CopyTo ( destination . Slice ( bytesWritten , KEY_MODIFIER_SIZE_IN_BYTES ) ) ;
243+ bytesWritten += KEY_MODIFIER_SIZE_IN_BYTES ;
244+ nonceBytes . CopyTo ( destination . Slice ( bytesWritten , NONCE_SIZE_IN_BYTES ) ) ;
245+ bytesWritten += NONCE_SIZE_IN_BYTES ;
250246
251- // At this point, retVal := { preBuffer | keyModifier | nonce | _____ | _____ | postBuffer }
247+ // At this point, destination := { keyModifier | nonce | _____ | _____ }
252248
253249 // Use the KDF to generate a new symmetric block cipher key
254250 // We'll need a temporary buffer to hold the symmetric encryption subkey
255- var decryptedKdk = new byte [ _keyDerivationKey . Length ] ;
256- var derivedKey = new byte [ _derivedkeySizeInBytes ] ;
257- fixed ( byte * __unused__1 = decryptedKdk )
251+ Span < byte > decryptedKdk = _keyDerivationKey . Length <= 256
252+ ? stackalloc byte [ 256 ] . Slice ( 0 , _keyDerivationKey . Length )
253+ : new byte [ _keyDerivationKey . Length ] ;
254+ var derivedKey = _derivedkeySizeInBytes <= 256
255+ ? stackalloc byte [ 256 ] . Slice ( 0 , _derivedkeySizeInBytes )
256+ : new byte [ _derivedkeySizeInBytes ] ;
257+
258+ fixed ( byte * decryptedKdkUnsafe = decryptedKdk )
258259 fixed ( byte * __unused__2 = derivedKey )
259260 {
260261 try
261262 {
262- _keyDerivationKey . WriteSecretIntoBuffer ( new ArraySegment < byte > ( decryptedKdk ) ) ;
263+ _keyDerivationKey . WriteSecretIntoBuffer ( decryptedKdkUnsafe , decryptedKdk . Length ) ;
263264 ManagedSP800_108_CTR_HMACSHA512 . DeriveKeys (
264265 kdk : decryptedKdk ,
265266 label : additionalAuthenticatedData ,
@@ -268,22 +269,25 @@ public byte[] Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additiona
268269 operationSubkey : derivedKey ,
269270 validationSubkey : Span < byte > . Empty /* filling in derivedKey only */ ) ;
270271
271- // do gcm
272- var nonce = new Span < byte > ( retVal , nonceOffset , NONCE_SIZE_IN_BYTES ) ;
273- var tag = new Span < byte > ( retVal , tagOffset , TAG_SIZE_IN_BYTES ) ;
274- var encrypted = new Span < byte > ( retVal , encryptedDataOffset , plaintext . Count ) ;
272+ // Perform GCM encryption. Destination buffer expected structure:
273+ // { keyModifier | nonce | encryptedData | authenticationTag }
274+ var nonce = destination . Slice ( KEY_MODIFIER_SIZE_IN_BYTES , NONCE_SIZE_IN_BYTES ) ;
275+ var encrypted = destination . Slice ( bytesWritten , plaintext . Length ) ;
276+ var tag = destination . Slice ( bytesWritten + plaintext . Length , TAG_SIZE_IN_BYTES ) ;
277+
275278 using var aes = new AesGcm ( derivedKey , TAG_SIZE_IN_BYTES ) ;
276279 aes . Encrypt ( nonce , plaintext , encrypted , tag ) ;
277280
278- // At this point, retVal := { preBuffer | keyModifier | nonce | encryptedData | authenticationTag | postBuffer }
281+ // At this point, destination := { keyModifier | nonce | encryptedData | authenticationTag }
279282 // And we're done!
280- return retVal ;
283+ bytesWritten += plaintext . Length + TAG_SIZE_IN_BYTES ;
284+ return true ;
281285 }
282286 finally
283287 {
284288 // delete since these contain secret material
285- Array . Clear ( decryptedKdk , 0 , decryptedKdk . Length ) ;
286- Array . Clear ( derivedKey , 0 , derivedKey . Length ) ;
289+ decryptedKdk . Clear ( ) ;
290+ derivedKey . Clear ( ) ;
287291 }
288292 }
289293 }
@@ -293,9 +297,7 @@ public byte[] Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additiona
293297 throw Error . CryptCommon_GenericError ( ex ) ;
294298 }
295299 }
296-
297- public byte [ ] Encrypt ( ArraySegment < byte > plaintext , ArraySegment < byte > additionalAuthenticatedData )
298- => Encrypt ( plaintext , additionalAuthenticatedData , 0 , 0 ) ;
300+ #endif
299301
300302 public void Dispose ( )
301303 {
0 commit comments