ci: add GitHub Pages deployment workflow for docs site Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
92 lines
2.5 KiB
Go
92 lines
2.5 KiB
Go
package device
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// encrypt is a test helper that encrypts using the same format as Python's AESGCM.
|
|
// This verifies Go-side decryption is compatible with Python-side encryption.
|
|
func encrypt(t *testing.T, plaintext []byte, key []byte) []byte {
|
|
t.Helper()
|
|
block, err := aes.NewCipher(key)
|
|
require.NoError(t, err)
|
|
gcm, err := cipher.NewGCM(block)
|
|
require.NoError(t, err)
|
|
nonce := make([]byte, 12)
|
|
_, err = rand.Read(nonce)
|
|
require.NoError(t, err)
|
|
// gcm.Seal appends ciphertext+tag after nonce
|
|
return gcm.Seal(nonce, nonce, plaintext, nil)
|
|
}
|
|
|
|
func TestDecryptCredentials_RoundTrip(t *testing.T) {
|
|
key := make([]byte, 32)
|
|
_, err := rand.Read(key)
|
|
require.NoError(t, err)
|
|
|
|
creds := credentialsJSON{Username: "admin", Password: "secret123"}
|
|
plaintext, err := json.Marshal(creds)
|
|
require.NoError(t, err)
|
|
|
|
ciphertext := encrypt(t, plaintext, key)
|
|
|
|
username, password, err := DecryptCredentials(ciphertext, key)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "admin", username)
|
|
assert.Equal(t, "secret123", password)
|
|
}
|
|
|
|
func TestDecryptCredentials_WrongKey(t *testing.T) {
|
|
key1 := make([]byte, 32)
|
|
key2 := make([]byte, 32)
|
|
_, _ = rand.Read(key1)
|
|
_, _ = rand.Read(key2)
|
|
|
|
creds := credentialsJSON{Username: "admin", Password: "secret"}
|
|
plaintext, _ := json.Marshal(creds)
|
|
ciphertext := encrypt(t, plaintext, key1)
|
|
|
|
_, _, err := DecryptCredentials(ciphertext, key2)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "wrong key or tampered")
|
|
}
|
|
|
|
func TestDecryptCredentials_ShortCiphertext(t *testing.T) {
|
|
key := make([]byte, 32)
|
|
_, _ = rand.Read(key)
|
|
|
|
_, _, err := DecryptCredentials([]byte("short"), key)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "too short")
|
|
}
|
|
|
|
func TestDecryptCredentials_WrongKeyLength(t *testing.T) {
|
|
_, _, err := DecryptCredentials(make([]byte, 50), make([]byte, 16))
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "32 bytes")
|
|
}
|
|
|
|
func TestDecryptCredentials_TamperedCiphertext(t *testing.T) {
|
|
key := make([]byte, 32)
|
|
_, _ = rand.Read(key)
|
|
|
|
creds := credentialsJSON{Username: "admin", Password: "secret"}
|
|
plaintext, _ := json.Marshal(creds)
|
|
ciphertext := encrypt(t, plaintext, key)
|
|
|
|
// Flip a byte in the encrypted portion (after 12-byte nonce)
|
|
tampered := make([]byte, len(ciphertext))
|
|
copy(tampered, ciphertext)
|
|
tampered[15] ^= 0xFF
|
|
|
|
_, _, err := DecryptCredentials(tampered, key)
|
|
assert.Error(t, err)
|
|
}
|