package salsa20
import (
"crypto/cipher"
"encoding/binary"
"golang.org/x/crypto/salsa20/salsa"
)
const BlockSize = 64
type salsaCipher struct {
key *[32 ]byte
nonce [8 ]byte
x [BlockSize ]byte
nx int
counter uint64
}
func New (key *[32 ]byte , nonce []byte ) cipher .Stream {
c := new (salsaCipher )
if len (nonce ) == 24 {
var subKey [32 ]byte
var hNonce [16 ]byte
copy (hNonce [:], nonce [:16 ])
salsa .HSalsa20 (&subKey , &hNonce , key , &salsa .Sigma )
copy (c .nonce [:], nonce [16 :])
c .key = &subKey
} else if len (nonce ) == 8 {
c .key = key
copy (c .nonce [:], nonce )
} else {
panic ("salsa20: nonce must be 8 or 24 bytes" )
}
return c
}
func (c *salsaCipher ) XORKeyStream (dst , src []byte ) {
if len (dst ) < len (src ) {
src = src [:len (dst )]
}
if c .nx > 0 {
n := xorBytes (dst , src , c .x [c .nx :])
c .nx += n
if c .nx == BlockSize {
c .nx = 0
}
src = src [n :]
dst = dst [n :]
}
if len (src ) > BlockSize {
n := len (src ) &^ (BlockSize - 1 )
c .blocks (dst , src [:n ])
src = src [n :]
dst = dst [n :]
}
if len (src ) > 0 {
c .nx = copy (c .x [:], src )
for i := c .nx ; i < len (c .x ); i ++ {
c .x [i ] = 0
}
c .blocks (c .x [:], c .x [:])
copy (dst , c .x [:c .nx ])
}
}
func (c *salsaCipher ) blocks (dst , src []byte ) {
var nonce [16 ]byte
copy (nonce [:], c .nonce [:])
binary .LittleEndian .PutUint64 (nonce [8 :], c .counter )
salsa .XORKeyStream (dst , src , &nonce , c .key )
c .counter += uint64 (len (src )) / 64
}
func xorBytes(dst , a , b []byte ) int {
n := len (a )
if len (b ) < n {
n = len (b )
}
for i := 0 ; i < n ; i ++ {
dst [i ] = a [i ] ^ b [i ]
}
return n
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .