Initial commit: crypto.go and protocol.go implementation + unit tests
This commit is contained in:
108
crypto_test.go
Normal file
108
crypto_test.go
Normal file
@@ -0,0 +1,108 @@
|
||||
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())
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user