yggdrasil-go/src/yggdrasil/crypto.go

168 lines
3.8 KiB
Go
Raw Normal View History

2017-12-29 04:16:20 +00:00
package yggdrasil
/*
This part of the package wraps crypto operations needed elsewhere
In particular, it exposes key generation for ed25519 and nacl box
It also defines NodeID and TreeID as hashes of keys, and wraps hash functions
*/
2018-06-12 22:50:08 +00:00
import (
"crypto/rand"
"crypto/sha512"
"golang.org/x/crypto/ed25519"
"golang.org/x/crypto/nacl/box"
)
2017-12-29 04:16:20 +00:00
////////////////////////////////////////////////////////////////////////////////
// NodeID and TreeID
const NodeIDLen = sha512.Size
const TreeIDLen = sha512.Size
const handleLen = 8
type NodeID [NodeIDLen]byte
type TreeID [TreeIDLen]byte
type handle [handleLen]byte
func getNodeID(pub *boxPubKey) *NodeID {
2018-01-04 22:37:51 +00:00
h := sha512.Sum512(pub[:])
return (*NodeID)(&h)
2017-12-29 04:16:20 +00:00
}
func getTreeID(pub *sigPubKey) *TreeID {
2018-01-04 22:37:51 +00:00
h := sha512.Sum512(pub[:])
return (*TreeID)(&h)
2017-12-29 04:16:20 +00:00
}
func newHandle() *handle {
2018-01-04 22:37:51 +00:00
var h handle
_, err := rand.Read(h[:])
if err != nil {
panic(err)
}
return &h
2017-12-29 04:16:20 +00:00
}
////////////////////////////////////////////////////////////////////////////////
// Signatures
const sigPubKeyLen = ed25519.PublicKeySize
const sigPrivKeyLen = ed25519.PrivateKeySize
const sigLen = ed25519.SignatureSize
type sigPubKey [sigPubKeyLen]byte
type sigPrivKey [sigPrivKeyLen]byte
type sigBytes [sigLen]byte
func newSigKeys() (*sigPubKey, *sigPrivKey) {
2018-01-04 22:37:51 +00:00
var pub sigPubKey
var priv sigPrivKey
pubSlice, privSlice, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
copy(pub[:], pubSlice)
copy(priv[:], privSlice)
return &pub, &priv
2017-12-29 04:16:20 +00:00
}
func sign(priv *sigPrivKey, msg []byte) *sigBytes {
2018-01-04 22:37:51 +00:00
var sig sigBytes
sigSlice := ed25519.Sign(priv[:], msg)
copy(sig[:], sigSlice)
return &sig
2017-12-29 04:16:20 +00:00
}
func verify(pub *sigPubKey, msg []byte, sig *sigBytes) bool {
2018-01-04 22:37:51 +00:00
// Should sig be an array instead of a slice?...
// It's fixed size, but
return ed25519.Verify(pub[:], msg, sig[:])
2017-12-29 04:16:20 +00:00
}
////////////////////////////////////////////////////////////////////////////////
// NaCl-like crypto "box" (curve25519+xsalsa20+poly1305)
const boxPubKeyLen = 32
const boxPrivKeyLen = 32
const boxSharedKeyLen = 32
const boxNonceLen = 24
const boxOverhead = box.Overhead
2017-12-29 04:16:20 +00:00
type boxPubKey [boxPubKeyLen]byte
type boxPrivKey [boxPrivKeyLen]byte
type boxSharedKey [boxSharedKeyLen]byte
type boxNonce [boxNonceLen]byte
func newBoxKeys() (*boxPubKey, *boxPrivKey) {
2018-01-04 22:37:51 +00:00
pubBytes, privBytes, err := box.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
pub := (*boxPubKey)(pubBytes)
priv := (*boxPrivKey)(privBytes)
return pub, priv
2017-12-29 04:16:20 +00:00
}
func getSharedKey(myPrivKey *boxPrivKey,
2018-01-04 22:37:51 +00:00
othersPubKey *boxPubKey) *boxSharedKey {
var shared [boxSharedKeyLen]byte
priv := (*[boxPrivKeyLen]byte)(myPrivKey)
pub := (*[boxPubKeyLen]byte)(othersPubKey)
box.Precompute(&shared, pub, priv)
return (*boxSharedKey)(&shared)
2017-12-29 04:16:20 +00:00
}
func boxOpen(shared *boxSharedKey,
2018-01-04 22:37:51 +00:00
boxed []byte,
nonce *boxNonce) ([]byte, bool) {
out := util_getBytes()
s := (*[boxSharedKeyLen]byte)(shared)
n := (*[boxNonceLen]byte)(nonce)
unboxed, success := box.OpenAfterPrecomputation(out, boxed, n, s)
return unboxed, success
2017-12-29 04:16:20 +00:00
}
func boxSeal(shared *boxSharedKey, unboxed []byte, nonce *boxNonce) ([]byte, *boxNonce) {
2018-01-04 22:37:51 +00:00
if nonce == nil {
nonce = newBoxNonce()
}
nonce.update()
out := util_getBytes()
s := (*[boxSharedKeyLen]byte)(shared)
n := (*[boxNonceLen]byte)(nonce)
boxed := box.SealAfterPrecomputation(out, unboxed, n, s)
return boxed, nonce
2017-12-29 04:16:20 +00:00
}
func newBoxNonce() *boxNonce {
2018-01-04 22:37:51 +00:00
var nonce boxNonce
_, err := rand.Read(nonce[:])
for ; err == nil && nonce[0] == 0xff; _, err = rand.Read(nonce[:]) {
// Make sure nonce isn't too high
// This is just to make rollover unlikely to happen
// Rollover is fine, but it may kill the session and force it to reopen
}
if err != nil {
panic(err)
}
return &nonce
2017-12-29 04:16:20 +00:00
}
func (n *boxNonce) update() {
2018-01-04 22:37:51 +00:00
oldNonce := *n
n[len(n)-1] += 2
for i := len(n) - 2; i >= 0; i-- {
if n[i+1] < oldNonce[i+1] {
n[i] += 1
}
}
2017-12-29 04:16:20 +00:00
}