package noise
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"encoding/binary"
"hash"
"io"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/curve25519"
)
type DHKey struct {
Private []byte
Public []byte
}
type DHFunc interface {
GenerateKeypair (random io .Reader ) (DHKey , error )
DH (privkey, pubkey []byte ) ([]byte , error )
DHLen () int
DHName () string
}
type HashFunc interface {
Hash () hash .Hash
HashName () string
}
type CipherFunc interface {
Cipher (k [32 ]byte ) Cipher
CipherName () string
}
type Cipher interface {
Encrypt (out []byte , n uint64 , ad, plaintext []byte ) []byte
Decrypt (out []byte , n uint64 , ad, ciphertext []byte ) ([]byte , error )
}
type CipherSuite interface {
DHFunc
CipherFunc
HashFunc
Name () []byte
}
func NewCipherSuite (dh DHFunc , c CipherFunc , h HashFunc ) CipherSuite {
return ciphersuite {
DHFunc : dh ,
CipherFunc : c ,
HashFunc : h ,
name : []byte (dh .DHName () + "_" + c .CipherName () + "_" + h .HashName ()),
}
}
type ciphersuite struct {
DHFunc
CipherFunc
HashFunc
name []byte
}
func (s ciphersuite ) Name () []byte { return s .name }
var DH25519 DHFunc = dh25519 {}
type dh25519 struct {}
func (dh25519 ) GenerateKeypair (rng io .Reader ) (DHKey , error ) {
privkey := make ([]byte , 32 )
if rng == nil {
rng = rand .Reader
}
if _ , err := io .ReadFull (rng , privkey ); err != nil {
return DHKey {}, err
}
pubkey , err := curve25519 .X25519 (privkey , curve25519 .Basepoint )
if err != nil {
return DHKey {}, err
}
return DHKey {Private : privkey , Public : pubkey }, nil
}
func (dh25519 ) DH (privkey , pubkey []byte ) ([]byte , error ) {
return curve25519 .X25519 (privkey , pubkey )
}
func (dh25519 ) DHLen () int { return 32 }
func (dh25519 ) DHName () string { return "25519" }
type cipherFn struct {
fn func ([32 ]byte ) Cipher
name string
}
func (c cipherFn ) Cipher (k [32 ]byte ) Cipher { return c .fn (k ) }
func (c cipherFn ) CipherName () string { return c .name }
var CipherAESGCM CipherFunc = cipherFn {cipherAESGCM , "AESGCM" }
func cipherAESGCM(k [32 ]byte ) Cipher {
c , err := aes .NewCipher (k [:])
if err != nil {
panic (err )
}
gcm , err := cipher .NewGCM (c )
if err != nil {
panic (err )
}
return aeadCipher {
gcm ,
func (n uint64 ) []byte {
var nonce [12 ]byte
binary .BigEndian .PutUint64 (nonce [4 :], n )
return nonce [:]
},
}
}
var CipherChaChaPoly CipherFunc = cipherFn {cipherChaChaPoly , "ChaChaPoly" }
func cipherChaChaPoly(k [32 ]byte ) Cipher {
c , err := chacha20poly1305 .New (k [:])
if err != nil {
panic (err )
}
return aeadCipher {
c ,
func (n uint64 ) []byte {
var nonce [12 ]byte
binary .LittleEndian .PutUint64 (nonce [4 :], n )
return nonce [:]
},
}
}
type aeadCipher struct {
cipher .AEAD
nonce func (uint64 ) []byte
}
func (c aeadCipher ) Encrypt (out []byte , n uint64 , ad , plaintext []byte ) []byte {
return c .Seal (out , c .nonce (n ), plaintext , ad )
}
func (c aeadCipher ) Decrypt (out []byte , n uint64 , ad , ciphertext []byte ) ([]byte , error ) {
return c .Open (out , c .nonce (n ), ciphertext , ad )
}
type hashFn struct {
fn func () hash .Hash
name string
}
func (h hashFn ) Hash () hash .Hash { return h .fn () }
func (h hashFn ) HashName () string { return h .name }
var HashSHA256 HashFunc = hashFn {sha256 .New , "SHA256" }
var HashSHA512 HashFunc = hashFn {sha512 .New , "SHA512" }
func blake2bNew() hash .Hash {
h , err := blake2b .New512 (nil )
if err != nil {
panic (err )
}
return h
}
var HashBLAKE2b HashFunc = hashFn {blake2bNew , "BLAKE2b" }
func blake2sNew() hash .Hash {
h , err := blake2s .New256 (nil )
if err != nil {
panic (err )
}
return h
}
var HashBLAKE2s HashFunc = hashFn {blake2sNew , "BLAKE2s" }
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 .