mirror of
https://github.com/onsonr/sonr.git
synced 2025-03-10 21:09:11 +00:00
- **refactor: remove unused auth components** - **refactor: improve devbox configuration and deployment process** - **refactor: improve devnet and testnet setup** - **fix: update templ version to v0.2.778** - **refactor: rename pkl/net.matrix to pkl/matrix.net** - **refactor: migrate webapp components to nebula** - **refactor: protobuf types** - **chore: update dependencies for improved security and stability** - **feat: implement landing page and vault gateway servers** - **refactor: Migrate data models to new module structure and update related files** - **feature/1121-implement-ucan-validation** - **refactor: Replace hardcoded constants with model types in attns.go** - **feature/1121-implement-ucan-validation** - **chore: add origin Host struct and update main function to handle multiple hosts** - **build: remove unused static files from dwn module** - **build: remove unused static files from dwn module** - **refactor: Move DWN models to common package** - **refactor: move models to pkg/common** - **refactor: move vault web app assets to embed module** - **refactor: update session middleware import path** - **chore: configure port labels and auto-forwarding behavior** - **feat: enhance devcontainer configuration** - **feat: Add UCAN middleware for Echo with flexible token validation** - **feat: add JWT middleware for UCAN authentication** - **refactor: update package URI and versioning in PklProject files** - **fix: correct sonr.pkl import path** - **refactor: move JWT related code to auth package** - **feat: introduce vault configuration retrieval and management** - **refactor: Move vault components to gateway module and update file paths** - **refactor: remove Dexie and SQLite database implementations** - **feat: enhance frontend with PWA features and WASM integration** - **feat: add Devbox features and streamline Dockerfile** - **chore: update dependencies to include TigerBeetle** - **chore(deps): update go version to 1.23** - **feat: enhance devnet setup with PATH environment variable and updated PWA manifest** - **fix: upgrade tigerbeetle-go dependency and remove indirect dependency** - **feat: add PostgreSQL support to devnet and testnet deployments** - **refactor: rename keyshare cookie to token cookie** - **feat: upgrade Go version to 1.23.3 and update dependencies** - **refactor: update devnet and testnet configurations** - **feat: add IPFS configuration for devnet** - **I'll help you update the ipfs.config.pkl to include all the peers from the shell script. Here's the updated configuration:** - **refactor: move mpc package to crypto directory** - **feat: add BIP32 support for various cryptocurrencies** - **feat: enhance ATN.pkl with additional capabilities** - **refactor: simplify smart account and vault attenuation creation** - **feat: add new capabilities to the Attenuation type** - **refactor: Rename MPC files for clarity and consistency** - **feat: add DIDKey support for cryptographic operations** - **feat: add devnet and testnet deployment configurations** - **fix: correct key derivation in bip32 package** - **refactor: rename crypto/bip32 package to crypto/accaddr** - **fix: remove duplicate indirect dependency** - **refactor: move vault package to root directory** - **refactor: update routes for gateway and vault** - **refactor: remove obsolete web configuration file** - **refactor: remove unused TigerBeetle imports and update host configuration** - **refactor: adjust styles directory path** - **feat: add broadcastTx and simulateTx functions to gateway** - **feat: add PinVault handler**
245 lines
6.4 KiB
Go
245 lines
6.4 KiB
Go
package daed
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/subtle"
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
// Placeholder for internal crypto/cipher allowlist, please ignore.
|
|
// Placeholder for internal crypto/subtle allowlist, please ignore.
|
|
)
|
|
|
|
// AESSIV is an implementation of AES-SIV-CMAC as defined in
|
|
// https://tools.ietf.org/html/rfc5297.
|
|
//
|
|
// AESSIV implements a deterministic encryption with associated data (i.e. the
|
|
// DeterministicAEAD interface). Hence the implementation below is restricted
|
|
// to one AD component.
|
|
//
|
|
// Security Note:
|
|
//
|
|
// Chatterjee, Menezes and Sarkar analyze AES-SIV in Section 5.1 of
|
|
// https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf
|
|
//
|
|
// Their analysis shows that AES-SIV is susceptible to an attack in
|
|
// a multi-user setting. Concretely, if an attacker knows the encryption
|
|
// of a message m encrypted and authenticated with k different keys,
|
|
// then it is possible to find one of the MAC keys in time 2^b / k
|
|
// where b is the size of the MAC key. A consequence of this attack
|
|
// is that 128-bit MAC keys give unsufficient security.
|
|
// Since 192-bit AES keys are not supported by tink for voodoo reasons
|
|
// and RFC 5297 only supports same size encryption and MAC keys this
|
|
// implies that keys must be 64 bytes (2*256 bits) long.
|
|
type AESSIV struct {
|
|
Cipher cipher.Block
|
|
K1 []byte
|
|
K2 []byte
|
|
CmacK1 []byte
|
|
CmacK2 []byte
|
|
}
|
|
|
|
const (
|
|
// AESSIVKeySize is the key size in bytes.
|
|
AESSIVKeySize = 64
|
|
|
|
intSize = 32 << (^uint(0) >> 63) // 32 or 64
|
|
maxInt = 1<<(intSize-1) - 1
|
|
)
|
|
|
|
// NewAESSIV returns an AESSIV instance.
|
|
func NewAESSIV(key []byte) (*AESSIV, error) {
|
|
if len(key) != AESSIVKeySize {
|
|
return nil, fmt.Errorf("aes_siv: invalid key size %d", len(key))
|
|
}
|
|
|
|
k1 := key[:32]
|
|
k2 := key[32:]
|
|
c, err := aes.NewCipher(k1)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("aes_siv: aes.NewCipher(%s) failed, %v", k1, err)
|
|
}
|
|
|
|
block := make([]byte, aes.BlockSize)
|
|
c.Encrypt(block, block)
|
|
multiplyByX(block)
|
|
cmacK1 := make([]byte, aes.BlockSize)
|
|
copy(cmacK1, block)
|
|
multiplyByX(block)
|
|
cmacK2 := make([]byte, aes.BlockSize)
|
|
copy(cmacK2, block)
|
|
|
|
return &AESSIV{
|
|
K1: k1,
|
|
K2: k2,
|
|
CmacK1: cmacK1,
|
|
CmacK2: cmacK2,
|
|
Cipher: c,
|
|
}, nil
|
|
}
|
|
|
|
// multiplyByX multiplies an element in GF(2^128) by its generator.
|
|
//
|
|
// This function is incorrectly named "doubling" in section 2.3 of RFC 5297.
|
|
func multiplyByX(block []byte) {
|
|
carry := int(block[0] >> 7)
|
|
for i := 0; i < aes.BlockSize-1; i++ {
|
|
block[i] = (block[i] << 1) | (block[i+1] >> 7)
|
|
}
|
|
|
|
block[aes.BlockSize-1] = (block[aes.BlockSize-1] << 1) ^ byte(subtle.ConstantTimeSelect(carry, 0x87, 0x00))
|
|
}
|
|
|
|
// EncryptDeterministically deterministically encrypts plaintext with associatedData.
|
|
func (asc *AESSIV) EncryptDeterministically(plaintext, associatedData []byte) ([]byte, error) {
|
|
if len(plaintext) > maxInt-aes.BlockSize {
|
|
return nil, fmt.Errorf("aes_siv: plaintext too long")
|
|
}
|
|
siv := make([]byte, aes.BlockSize)
|
|
asc.s2v(plaintext, associatedData, siv)
|
|
|
|
ct := make([]byte, len(plaintext)+aes.BlockSize)
|
|
copy(ct[:aes.BlockSize], siv)
|
|
if err := asc.ctrCrypt(siv, plaintext, ct[aes.BlockSize:]); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ct, nil
|
|
}
|
|
|
|
// DecryptDeterministically deterministically decrypts ciphertext with associatedData.
|
|
func (asc *AESSIV) DecryptDeterministically(ciphertext, associatedData []byte) ([]byte, error) {
|
|
if len(ciphertext) < aes.BlockSize {
|
|
return nil, errors.New("aes_siv: ciphertext is too short")
|
|
}
|
|
|
|
pt := make([]byte, len(ciphertext)-aes.BlockSize)
|
|
siv := ciphertext[:aes.BlockSize]
|
|
asc.ctrCrypt(siv, ciphertext[aes.BlockSize:], pt)
|
|
s2v := make([]byte, aes.BlockSize)
|
|
asc.s2v(pt, associatedData, s2v)
|
|
|
|
diff := byte(0)
|
|
for i := 0; i < aes.BlockSize; i++ {
|
|
diff |= siv[i] ^ s2v[i]
|
|
}
|
|
if diff != 0 {
|
|
return nil, errors.New("aes_siv: invalid ciphertext")
|
|
}
|
|
|
|
return pt, nil
|
|
}
|
|
|
|
// ctrCrypt encrypts (or decrypts) the bytes in in using an SIV and writes the
|
|
// result to out.
|
|
func (asc *AESSIV) ctrCrypt(siv, in, out []byte) error {
|
|
// siv might be used outside of ctrCrypt(), so making a copy of it.
|
|
iv := make([]byte, aes.BlockSize)
|
|
copy(iv, siv)
|
|
iv[8] &= 0x7f
|
|
iv[12] &= 0x7f
|
|
|
|
c, err := aes.NewCipher(asc.K2)
|
|
if err != nil {
|
|
return fmt.Errorf("aes_siv: aes.NewCipher(%s) failed, %v", asc.K2, err)
|
|
}
|
|
|
|
steam := cipher.NewCTR(c, iv)
|
|
steam.XORKeyStream(out, in)
|
|
return nil
|
|
}
|
|
|
|
// s2v is a Pseudo-Random Function (PRF) construction:
|
|
// https://tools.ietf.org/html/rfc5297.
|
|
func (asc *AESSIV) s2v(msg, ad, siv []byte) {
|
|
block := make([]byte, aes.BlockSize)
|
|
asc.cmac(block, block)
|
|
multiplyByX(block)
|
|
|
|
adMac := make([]byte, aes.BlockSize)
|
|
asc.cmac(ad, adMac)
|
|
xorBlock(adMac, block)
|
|
|
|
if len(msg) >= aes.BlockSize {
|
|
asc.cmacLong(msg, block, siv)
|
|
} else {
|
|
multiplyByX(block)
|
|
for i := 0; i < len(msg); i++ {
|
|
block[i] ^= msg[i]
|
|
}
|
|
block[len(msg)] ^= 0x80
|
|
asc.cmac(block, siv)
|
|
}
|
|
}
|
|
|
|
// cmacLong computes CMAC(XorEnd(data, last)), where XorEnd xors the bytes in
|
|
// last to the last bytes in data.
|
|
//
|
|
// The size of the data must be at least 16 bytes.
|
|
func (asc *AESSIV) cmacLong(data, last, mac []byte) {
|
|
block := make([]byte, aes.BlockSize)
|
|
copy(block, data[:aes.BlockSize])
|
|
|
|
idx := aes.BlockSize
|
|
for aes.BlockSize <= len(data)-idx {
|
|
asc.Cipher.Encrypt(block, block)
|
|
xorBlock(data[idx:idx+aes.BlockSize], block)
|
|
idx += aes.BlockSize
|
|
}
|
|
|
|
remaining := len(data) - idx
|
|
for i := 0; i < aes.BlockSize-remaining; i++ {
|
|
block[remaining+i] ^= last[i]
|
|
}
|
|
if remaining == 0 {
|
|
xorBlock(asc.CmacK1, block)
|
|
} else {
|
|
asc.Cipher.Encrypt(block, block)
|
|
for i := 0; i < remaining; i++ {
|
|
block[i] ^= last[aes.BlockSize-remaining+i]
|
|
block[i] ^= data[idx+i]
|
|
}
|
|
block[remaining] ^= 0x80
|
|
xorBlock(asc.CmacK2, block)
|
|
}
|
|
|
|
asc.Cipher.Encrypt(mac, block)
|
|
}
|
|
|
|
// cmac computes a CMAC of some data.
|
|
func (asc *AESSIV) cmac(data, mac []byte) {
|
|
numBs := int(math.Ceil(float64(len(data)) / aes.BlockSize))
|
|
if numBs == 0 {
|
|
numBs = 1
|
|
}
|
|
lastBSize := len(data) - (numBs-1)*aes.BlockSize
|
|
|
|
block := make([]byte, aes.BlockSize)
|
|
idx := 0
|
|
for i := 0; i < numBs-1; i++ {
|
|
xorBlock(data[idx:idx+aes.BlockSize], block)
|
|
asc.Cipher.Encrypt(block, block)
|
|
idx += aes.BlockSize
|
|
}
|
|
for j := 0; j < lastBSize; j++ {
|
|
block[j] ^= data[idx+j]
|
|
}
|
|
|
|
if lastBSize == aes.BlockSize {
|
|
xorBlock(asc.CmacK1, block)
|
|
} else {
|
|
block[lastBSize] ^= 0x80
|
|
xorBlock(asc.CmacK2, block)
|
|
}
|
|
|
|
asc.Cipher.Encrypt(mac, block)
|
|
}
|
|
|
|
// xorBlock sets block[i] = x[i] ^ block[i].
|
|
func xorBlock(x, block []byte) {
|
|
for i := 0; i < aes.BlockSize; i++ {
|
|
block[i] ^= x[i]
|
|
}
|
|
}
|