mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
crypto.cipher: make Stream.xor_key_stream implementers require a mutable receiver (#21974)
This commit is contained in:
parent
485983ebd2
commit
a4b8768146
@ -18,12 +18,12 @@ fn test_aes_ctr() {
|
||||
|
||||
fn aes_ctr_en(mut src []u8, key []u8, iv []u8) {
|
||||
block := aes.new_cipher(key)
|
||||
mode := cipher.new_ctr(block, iv)
|
||||
mut mode := cipher.new_ctr(block, iv)
|
||||
mode.xor_key_stream(mut src, src.clone())
|
||||
}
|
||||
|
||||
fn aes_ctr_de(mut src []u8, key []u8, iv []u8) {
|
||||
block := aes.new_cipher(key)
|
||||
mode := cipher.new_ctr(block, iv)
|
||||
mut mode := cipher.new_ctr(block, iv)
|
||||
mode.xor_key_stream(mut src, src.clone())
|
||||
}
|
||||
|
@ -63,34 +63,34 @@ fn new_cfb(b Block, iv []u8, decrypt bool) Cfb {
|
||||
return x
|
||||
}
|
||||
|
||||
pub fn (mut x Cfb) xor_key_stream(mut dst_ []u8, src_ []u8) {
|
||||
pub fn (mut x Cfb) xor_key_stream(mut dst []u8, src []u8) {
|
||||
unsafe {
|
||||
mut dst := *dst_
|
||||
mut src := src_
|
||||
if dst.len < src.len {
|
||||
mut local_dst := *dst
|
||||
mut local_src := src
|
||||
if local_dst.len < local_src.len {
|
||||
panic('crypto.cipher.xor_key_stream: output smaller than input')
|
||||
}
|
||||
|
||||
if subtle.inexact_overlap(dst[..src.len], src) {
|
||||
if subtle.inexact_overlap(local_dst[..src.len], local_src) {
|
||||
panic('crypto.cipher.xor_key_stream: invalid buffer overlap')
|
||||
}
|
||||
|
||||
for src.len > 0 {
|
||||
for local_src.len > 0 {
|
||||
if x.out_used == x.out.len {
|
||||
x.b.encrypt(mut x.out, x.next)
|
||||
x.out_used = 0
|
||||
}
|
||||
|
||||
if x.decrypt {
|
||||
copy(mut x.next[x.out_used..], src)
|
||||
copy(mut x.next[x.out_used..], local_src)
|
||||
}
|
||||
|
||||
n := xor_bytes(mut dst, src, x.out[x.out_used..])
|
||||
n := xor_bytes(mut local_dst, local_src, x.out[x.out_used..])
|
||||
if !x.decrypt {
|
||||
copy(mut x.next[x.out_used..], dst)
|
||||
copy(mut x.next[x.out_used..], local_dst)
|
||||
}
|
||||
dst = dst[n..]
|
||||
src = src[n..]
|
||||
local_dst = local_dst[n..]
|
||||
local_src = local_src[n..]
|
||||
x.out_used += n
|
||||
}
|
||||
}
|
||||
|
18
vlib/crypto/cipher/cfb_test.v
Normal file
18
vlib/crypto/cipher/cfb_test.v
Normal file
@ -0,0 +1,18 @@
|
||||
import crypto.cipher
|
||||
import crypto.des
|
||||
|
||||
struct StreamCipher {
|
||||
cipher cipher.Stream
|
||||
}
|
||||
|
||||
fn test_cfb_stream_cipher() ! {
|
||||
key := '123456789012345678901234'.bytes()
|
||||
iv := 'abcdegfh'.bytes()
|
||||
|
||||
block := des.new_cipher(key[..8])
|
||||
c := cipher.new_cfb_encrypter(block, iv)
|
||||
|
||||
s := StreamCipher{
|
||||
cipher: c
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ pub interface Block {
|
||||
|
||||
// A Stream represents a stream cipher.
|
||||
pub interface Stream {
|
||||
mut:
|
||||
// xor_key_stream XORs each byte in the given slice with a byte from the
|
||||
// cipher's key stream. Dst and src must overlap entirely or not at all.
|
||||
//
|
||||
|
@ -49,25 +49,25 @@ pub fn new_ctr(b Block, iv []u8) Ctr {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (x &Ctr) xor_key_stream(mut dst_ []u8, src_ []u8) {
|
||||
pub fn (mut x Ctr) xor_key_stream(mut dst []u8, src []u8) {
|
||||
unsafe {
|
||||
mut dst := *dst_
|
||||
mut src := src_
|
||||
if dst.len < src.len {
|
||||
mut local_dst := *dst
|
||||
mut local_src := src
|
||||
if local_dst.len < local_src.len {
|
||||
panic('crypto.cipher.xor_key_stream: output smaller than input')
|
||||
}
|
||||
|
||||
if subtle.inexact_overlap(dst[..src.len], src) {
|
||||
if subtle.inexact_overlap(local_dst[..local_src.len], local_src) {
|
||||
panic('crypto.cipher.xor_key_stream: invalid buffer overlap')
|
||||
}
|
||||
|
||||
for src.len > 0 {
|
||||
for local_src.len > 0 {
|
||||
if x.out_used == x.out.len {
|
||||
x.b.encrypt(mut x.out, x.next)
|
||||
x.out_used = 0
|
||||
}
|
||||
|
||||
n := xor_bytes(mut dst, src, x.out[x.out_used..])
|
||||
n := xor_bytes(mut local_dst, local_src, x.out[x.out_used..])
|
||||
|
||||
// increment counter
|
||||
for i := x.next.len - 1; i >= 0; i-- {
|
||||
@ -77,8 +77,8 @@ pub fn (x &Ctr) xor_key_stream(mut dst_ []u8, src_ []u8) {
|
||||
}
|
||||
}
|
||||
|
||||
dst = dst[n..]
|
||||
src = src[n..]
|
||||
local_dst = local_dst[n..]
|
||||
local_src = local_src[n..]
|
||||
x.out_used += n
|
||||
}
|
||||
}
|
||||
|
18
vlib/crypto/cipher/ctr_test.v
Normal file
18
vlib/crypto/cipher/ctr_test.v
Normal file
@ -0,0 +1,18 @@
|
||||
import crypto.cipher
|
||||
import crypto.des
|
||||
|
||||
struct StreamCipher {
|
||||
cipher cipher.Stream
|
||||
}
|
||||
|
||||
fn test_ctr_stream_cipher() ! {
|
||||
key := '123456789012345678901234'.bytes()
|
||||
iv := 'abcdegfh'.bytes()
|
||||
|
||||
block := des.new_cipher(key[..8])
|
||||
c := cipher.new_ctr(block, iv)
|
||||
|
||||
s := StreamCipher{
|
||||
cipher: c
|
||||
}
|
||||
}
|
@ -29,24 +29,24 @@ fn test_des_ctr() {
|
||||
|
||||
fn des_ctr_en(mut src []u8, key []u8, iv []u8) {
|
||||
block := des.new_cipher(key)
|
||||
mode := cipher.new_ctr(block, iv)
|
||||
mut mode := cipher.new_ctr(block, iv)
|
||||
mode.xor_key_stream(mut src, src.clone())
|
||||
}
|
||||
|
||||
fn des_ctr_de(mut src []u8, key []u8, iv []u8) {
|
||||
block := des.new_cipher(key)
|
||||
mode := cipher.new_ctr(block, iv)
|
||||
mut mode := cipher.new_ctr(block, iv)
|
||||
mode.xor_key_stream(mut src, src.clone())
|
||||
}
|
||||
|
||||
fn triple_des_ctr_en(mut src []u8, key []u8, iv []u8) {
|
||||
block := des.new_triple_des_cipher(key)
|
||||
mode := cipher.new_ctr(block, iv)
|
||||
mut mode := cipher.new_ctr(block, iv)
|
||||
mode.xor_key_stream(mut src, src.clone())
|
||||
}
|
||||
|
||||
fn triple_des_ctr_de(mut src []u8, key []u8, iv []u8) {
|
||||
block := des.new_triple_des_cipher(key)
|
||||
mode := cipher.new_ctr(block, iv)
|
||||
mut mode := cipher.new_ctr(block, iv)
|
||||
mode.xor_key_stream(mut src, src.clone())
|
||||
}
|
||||
|
@ -35,19 +35,19 @@ pub fn new_ofb(b Block, iv []u8) Ofb {
|
||||
return x
|
||||
}
|
||||
|
||||
pub fn (mut x Ofb) xor_key_stream(mut dst_ []u8, src_ []u8) {
|
||||
pub fn (mut x Ofb) xor_key_stream(mut dst []u8, src []u8) {
|
||||
unsafe {
|
||||
mut dst := *dst_
|
||||
mut src := src_
|
||||
if dst.len < src.len {
|
||||
mut local_dst := *dst
|
||||
mut local_src := src
|
||||
if local_dst.len < local_src.len {
|
||||
panic('crypto.cipher.xor_key_stream: output smaller than input')
|
||||
}
|
||||
|
||||
if subtle.inexact_overlap(dst[..src.len], src) {
|
||||
if subtle.inexact_overlap(local_dst[..local_src.len], local_src) {
|
||||
panic('crypto.cipher.xor_key_stream: invalid buffer overlap')
|
||||
}
|
||||
|
||||
for src.len > 0 {
|
||||
for local_src.len > 0 {
|
||||
if x.out_used == x.out.len {
|
||||
x.b.encrypt(mut x.out, x.next)
|
||||
x.out_used = 0
|
||||
@ -55,9 +55,9 @@ pub fn (mut x Ofb) xor_key_stream(mut dst_ []u8, src_ []u8) {
|
||||
|
||||
copy(mut x.next, x.out)
|
||||
|
||||
n := xor_bytes(mut dst, src, x.out)
|
||||
dst = dst[n..]
|
||||
src = src[n..]
|
||||
n := xor_bytes(mut local_dst, local_src, x.out)
|
||||
local_dst = local_dst[n..]
|
||||
local_src = local_src[n..]
|
||||
x.out_used += n
|
||||
}
|
||||
}
|
||||
|
18
vlib/crypto/cipher/ofb_test.v
Normal file
18
vlib/crypto/cipher/ofb_test.v
Normal file
@ -0,0 +1,18 @@
|
||||
import crypto.cipher
|
||||
import crypto.des
|
||||
|
||||
struct StreamCipher {
|
||||
cipher cipher.Stream
|
||||
}
|
||||
|
||||
fn test_ctr_stream_cipher() ! {
|
||||
key := '123456789012345678901234'.bytes()
|
||||
iv := 'abcdegfh'.bytes()
|
||||
|
||||
block := des.new_cipher(key[..8])
|
||||
c := cipher.new_ofb(block, iv)
|
||||
|
||||
s := StreamCipher{
|
||||
cipher: c
|
||||
}
|
||||
}
|
@ -65,7 +65,7 @@ pub fn (mut c Cipher) reset() {
|
||||
|
||||
// xor_key_stream sets dst to the result of XORing src with the key stream.
|
||||
// Dst and src must overlap entirely or not at all.
|
||||
pub fn (mut c Cipher) xor_key_stream(mut dst []u8, mut src []u8) {
|
||||
pub fn (mut c Cipher) xor_key_stream(mut dst []u8, src []u8) {
|
||||
if src.len == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -1,8 +1,22 @@
|
||||
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
import crypto.cipher
|
||||
import crypto.rc4
|
||||
|
||||
struct StreamCipher {
|
||||
cipher cipher.Stream
|
||||
}
|
||||
|
||||
fn test_cfb_stream_cipher() ! {
|
||||
key := 'tthisisourrc4key'.bytes()
|
||||
c := rc4.new_cipher(key)!
|
||||
|
||||
s := StreamCipher{
|
||||
cipher: c
|
||||
}
|
||||
}
|
||||
|
||||
fn test_crypto_rc4() {
|
||||
key := 'tthisisourrc4key'.bytes()
|
||||
|
||||
@ -14,7 +28,7 @@ fn test_crypto_rc4() {
|
||||
mut src := 'toencrypt'.bytes()
|
||||
|
||||
// src & dst same, encrypt in place
|
||||
c.xor_key_stream(mut src, mut src) // encrypt data
|
||||
c.xor_key_stream(mut src, src) // encrypt data
|
||||
|
||||
c.reset()
|
||||
|
||||
|
@ -1,8 +1,27 @@
|
||||
module chacha20
|
||||
|
||||
import crypto.cipher
|
||||
import rand
|
||||
import encoding.hex
|
||||
|
||||
struct StreamCipher {
|
||||
mut:
|
||||
cipher &cipher.Stream
|
||||
}
|
||||
|
||||
// Verify chahca20.Cipher implements chiper.Stream correctly.
|
||||
fn test_chacha20_stream_cipher() ! {
|
||||
mut key := []u8{len: 32}
|
||||
mut nonce := []u8{len: 12}
|
||||
rand.read(mut key)
|
||||
rand.read(mut nonce)
|
||||
|
||||
mut c := new_cipher(key, nonce)!
|
||||
s := StreamCipher{
|
||||
cipher: c
|
||||
}
|
||||
}
|
||||
|
||||
fn test_chacha20_cipher_reset() ! {
|
||||
mut key := []u8{len: 32}
|
||||
mut nonce := []u8{len: 12}
|
||||
|
Loading…
x
Reference in New Issue
Block a user