Files
ownwire-go-sdk/crypto_test.go

109 lines
2.7 KiB
Go
Raw Normal View History

package ownwire_sdk_test
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
sdk "ownwire.net/ownwire-sdk"
)
func derive_nonce_reference(shared_key [32]byte, session_uuid_bytes [16]byte, salt16 [16]byte, seq_num uint64, is_response bool) [12]byte {
seq_be8 := [8]byte{}
for i := 7; i >= 0; i-- {
seq_be8[i] = byte(seq_num & 0xff)
seq_num >>= 8
}
flag := byte(0)
if is_response {
flag = 1
}
mac := hmac.New(sha256.New, shared_key[:])
mac.Write([]byte("ownwire/v1:gcm-nonce"))
mac.Write(session_uuid_bytes[:])
mac.Write(salt16[:])
mac.Write(seq_be8[:])
mac.Write([]byte{flag})
sum := mac.Sum(nil)
var iv [12]byte
copy(iv[:], sum[:12])
return iv
}
var _ = Describe("Crypto", func() {
It("parses UUID bytes", func() {
uuid_str := "cb653f53-6f7d-4aeb-ba0d-d2b17c290d8a"
uuid_bytes, err := sdk.ParseUUIDBytes(uuid_str)
Expect(err).To(BeNil())
Expect(hex.EncodeToString(uuid_bytes[:])).To(Equal("cb653f536f7d4aebba0dd2b17c290d8a"))
})
It("derives nonce exactly as reference implementation", func() {
var shared_key [32]byte
for i := 0; i < 32; i++ {
shared_key[i] = byte(i)
}
uuid_bytes, err := sdk.ParseUUIDBytes("cb653f53-6f7d-4aeb-ba0d-d2b17c290d8a")
Expect(err).To(BeNil())
var salt16 [16]byte
for i := 0; i < 16; i++ {
salt16[i] = byte(0xa0 + i)
}
seq_num := uint64(0x0102030405060708)
got := sdk.DeriveNonce(shared_key, uuid_bytes, salt16, seq_num, false)
want := derive_nonce_reference(shared_key, uuid_bytes, salt16, seq_num, false)
Expect(got).To(Equal(want))
})
It("encrypts and decrypts roundtrip", func() {
var shared_key [32]byte
for i := 0; i < 32; i++ {
shared_key[i] = byte(0x55 ^ i)
}
uuid_bytes, err := sdk.ParseUUIDBytes("cb653f53-6f7d-4aeb-ba0d-d2b17c290d8a")
Expect(err).To(BeNil())
plain_text := []byte("hello ownwire")
seq_num := uint64(123)
enc, err := sdk.EncryptAESGCM(shared_key, uuid_bytes, plain_text, seq_num, false)
Expect(err).To(BeNil())
Expect(enc.ContentB64).ToNot(BeEmpty())
Expect(enc.SaltHex).To(HaveLen(32)) // 16 bytes hex
out, err := sdk.DecryptAESGCM(shared_key, uuid_bytes, enc.ContentB64, enc.SaltHex, seq_num, false)
Expect(err).To(BeNil())
Expect(string(out)).To(Equal(string(plain_text)))
})
It("fails decrypt if seq changes", func() {
var shared_key [32]byte
for i := 0; i < 32; i++ {
shared_key[i] = byte(0x11 + i)
}
uuid_bytes, err := sdk.ParseUUIDBytes("cb653f53-6f7d-4aeb-ba0d-d2b17c290d8a")
Expect(err).To(BeNil())
enc, err := sdk.EncryptAESGCM(shared_key, uuid_bytes, []byte("hello"), 1, false)
Expect(err).To(BeNil())
_, err = sdk.DecryptAESGCM(shared_key, uuid_bytes, enc.ContentB64, enc.SaltHex, 2, false)
Expect(err).ToNot(BeNil())
})
})