@@ -61,13 +61,23 @@ pub fn new_cipher(key []u8, nonce []u8) !&Cipher {
61
61
// and XChaCha20 with 192 bits nonce. Internally, encrypt start with 0's counter value.
62
62
// If you want more control, use Cipher instance and setup the counter by your self.
63
63
pub fn encrypt (key []u8 , nonce []u8 , plaintext []u8 ) ! []u8 {
64
- return encrypt_with_counter (key, nonce, u32 (0 ), plaintext)
64
+ mut c := new_cipher (key, nonce)!
65
+ mut out := []u8 {len: plaintext.len}
66
+
67
+ c.encrypt (mut out, plaintext)
68
+ unsafe { c.reset () }
69
+ return out
65
70
}
66
71
67
72
// decrypt does reverse of encrypt operation by decrypting ciphertext with ChaCha20 cipher
68
73
// instance with provided key and nonce.
69
74
pub fn decrypt (key []u8 , nonce []u8 , ciphertext []u8 ) ! []u8 {
70
- return encrypt_with_counter (key, nonce, u32 (0 ), ciphertext)
75
+ mut c := new_cipher (key, nonce)!
76
+ mut out := []u8 {len: ciphertext.len}
77
+
78
+ c.encrypt (mut out, ciphertext)
79
+ unsafe { c.reset () }
80
+ return out
71
81
}
72
82
73
83
// xor_key_stream xors each byte in the given slice in the src with a byte from the
@@ -192,9 +202,19 @@ pub fn (mut c Cipher) encrypt(mut dst []u8, src []u8) {
192
202
}
193
203
}
194
204
195
- // chacha20_block_generic generates ChaCha20 generic keystream
205
+ // chacha20_block_generic generates a generic ChaCha20 keystream.
206
+ // This is main building block for ChaCha20 keystream generator.
207
+ // This routine was intended to work only for msg source with multiples of block_size in size.
196
208
@[direct_array_access]
197
209
fn (mut c Cipher) chacha20_block_generic (mut dst []u8 , src []u8 ) {
210
+ // ChaCha20 keystream generator was relatively easy to understand.
211
+ // Its contains steps:
212
+ // - Loads current ChaCha20 into temporary state, used for later.
213
+ // - Performs quarter_round function on this state and returns some new state.
214
+ // - Adds back the new state with the old state.
215
+ // - Performs xor-ing between src bytes (loaded as little endian number) with result from previous step.
216
+ // - Serializes, in little endian form, this xor-ed state into destination buffer.
217
+ //
198
218
// Makes sure its works for size of multiple of block_size
199
219
if dst.len != src.len || dst.len % block_size != 0 {
200
220
panic ('chacha20: internal error: wrong dst and/or src length' )
@@ -370,10 +390,6 @@ fn (mut c Cipher) do_rekey(key []u8, nonce []u8) ! {
370
390
return error ('chacha20: wrong nonce size' )
371
391
}
372
392
373
- // bounds check elimination hint
374
- _ = keys[key_size - 1 ]
375
- _ = nonces[nonce_size - 1 ]
376
-
377
393
// setup ChaCha20 cipher key
378
394
c.key[0 ] = binary.little_endian_u32 (keys[0 ..4 ])
379
395
c.key[1 ] = binary.little_endian_u32 (keys[4 ..8 ])
@@ -426,33 +442,3 @@ fn quarter_round(a u32, b u32, c u32, d u32) (u32, u32, u32, u32) {
426
442
427
443
return ax, bx, cx, dx
428
444
}
429
-
430
- // encrypt_with_counter encrypts plaintext with internal counter set to ctr
431
- fn encrypt_with_counter (key []u8 , nonce []u8 , ctr u32 , plaintext []u8 ) ! []u8 {
432
- if key.len != key_size {
433
- return error ('bad key size' )
434
- }
435
- if nonce.len == x_nonce_size {
436
- ciphertext := xchacha20_encrypt_with_counter (key, nonce, ctr, plaintext)!
437
- return ciphertext
438
- }
439
- if nonce.len == nonce_size {
440
- ciphertext := chacha20_encrypt_with_counter (key, nonce, ctr, plaintext)!
441
- return ciphertext
442
- }
443
- return error ('Wrong nonce size' )
444
- }
445
-
446
- fn chacha20_encrypt (key []u8 , nonce []u8 , plaintext []u8 ) ! []u8 {
447
- return chacha20_encrypt_with_counter (key, nonce, u32 (0 ), plaintext)
448
- }
449
-
450
- fn chacha20_encrypt_with_counter (key []u8 , nonce []u8 , ctr u32 , plaintext []u8 ) ! []u8 {
451
- mut c := new_cipher (key, nonce)!
452
- c.set_counter (ctr)
453
- mut out := []u8 {len: plaintext.len}
454
-
455
- c.encrypt (mut out, plaintext)
456
-
457
- return out
458
- }
0 commit comments