Documentation
¶
Overview ¶
Package encryption SQLCipher-style page-level transparent encryption. AES-256-CBC per-page encryption + HMAC-SHA256 integrity verification. Inserted at the Pager layer, invisible to upper SQL/BTree/MVCC layers.
Package encryption - 加密头(存储于页 0 MetaPage 之后的预留空间)
Package encryption - 密钥派生函数(PBKDF2-SHA256)
Index ¶
- Constants
- Variables
- func DeriveKeys(passphrase string, salt []byte) (encKey, macKey []byte, err error)
- func DeriveKeysFromRaw(rawKey []byte) (encKey, macKey []byte, err error)
- func GenerateSalt() ([]byte, error)
- func IsEncrypted(page0 []byte) bool
- type EncryptionHeader
- type EncryptionType
- type PageCipher
- func (pc *PageCipher) Clear()
- func (pc *PageCipher) DecryptBlob(ciphertext []byte, id uint32) ([]byte, error)
- func (pc *PageCipher) DecryptPage(data []byte, pageID uint32) ([]byte, error)
- func (pc *PageCipher) DecryptVerificationBlock(data []byte) ([]byte, error)
- func (pc *PageCipher) EncryptBlob(plaintext []byte, id uint32) ([]byte, error)
- func (pc *PageCipher) EncryptPage(plaintext []byte, pageID uint32) ([]byte, error)
- func (pc *PageCipher) EncryptVerificationBlock() ([]byte, error)
Constants ¶
const EncryptionHeaderMagic uint32 = 0x56445345
EncryptionHeaderMagic 加密数据库标识 "VDSE"(VDS Encrypted)
const EncryptionHeaderOffset = 49
EncryptionHeaderOffset 加密头在页 0 中的偏移(MetaPage 49 字节之后)
const EncryptionHeaderSize = 112
EncryptionHeaderSize 加密头序列化大小
const HMACSize = 16
HMACSize per-page integrity tag size (16 bytes)
const HeaderVersion = 3
HeaderVersion 加密头格式版本。 版本 1:确定性 IV(deriveIV(pageID)),页格式 = pageSize + HMACSize,零 IV 验证块 版本 2:非确定性 IV(nonce XOR deriveIV(pageID)),页格式 = NonceSize + pageSize + HMACSize,零 IV 验证块 版本 3:与版本 2 相同,验证块使用随机 nonce(nonce XOR deriveIV(0))
const KeySize = 32
KeySize AES-256 key size
const NonceSize = 8
NonceSize per-page random nonce size, stored as prefix of encrypted page. Used to derive a non-deterministic IV so identical plaintext pages produce different ciphertext.
const PBKDF2Iterations = 600000
PBKDF2Iterations 密钥派生迭代次数。 M3 修复:64000 → 600000,对齐 OWASP 2023 推荐值。 注意:升级后旧数据库的密钥派生使用新迭代数不影响解密(salt+passphrase 相同即可), 仅影响新建数据库或密钥重派生场景。
Variables ¶
var ErrHMACMismatch = errors.New("encryption: HMAC mismatch")
var ErrKeyInvalid = errors.New("encryption: invalid key")
Functions ¶
func DeriveKeys ¶
DeriveKeys 从 passphrase + salt 派生 encKey 和 macKey。
派生链:
masterKey = PBKDF2-SHA256(passphrase, salt, 64000, 32) encKey = HMAC-SHA256(masterKey, "vds-encryption-key")[0:32] macKey = HMAC-SHA256(masterKey, "vds-mac-key")[0:32]
两个独立 key 保证加密和完整性校验的密钥隔离, 即使 encKey 泄露也无法伪造 HMAC tag。
func DeriveKeysFromRaw ¶
DeriveKeysFromRaw 从原始 32 字节密钥派生 encKey 和 macKey。 用于开发者直接提供 AES-256 原始密钥(跳过 PBKDF2)。
func GenerateSalt ¶
GenerateSalt generates a 32-byte random salt for PBKDF2.
Types ¶
type EncryptionHeader ¶
type EncryptionHeader struct {
Magic uint32 // 0x56445345
Version uint32 // 1
Salt [32]byte // PBKDF2 随机盐
VerificationBlock [64]byte // 验证块密文(16 字节有效 + 48 字节 padding)
}
EncryptionHeader 页 0 中的加密元数据(明文存储,用于密钥验证)。
布局(112 字节):
Offset Size 字段
0 4 Magic: 0x56445345 ("VDSE")
4 4 Version
8 32 Salt (PBKDF2)
40 64 验证块密文(AES-256-CBC("VDS-KEY-VERIFY\x00"),恰好 1 个 block)
104 8 保留
func NewEncryptionHeader ¶
func NewEncryptionHeader(salt, verifyCiphertext []byte) (*EncryptionHeader, error)
NewEncryptionHeader 创建加密头。 salt 是 PBKDF2 随机盐,verifyCiphertext 是加密后的验证块。
func ReadEncryptionHeader ¶
func ReadEncryptionHeader(page0 []byte) (*EncryptionHeader, error)
ReadEncryptionHeader 从页 0 数据中读取加密头。
func (*EncryptionHeader) WriteTo ¶
func (h *EncryptionHeader) WriteTo(page0 []byte)
WriteTo 将加密头写入页 0 数据缓冲区(从 EncryptionHeaderOffset 开始)。
type EncryptionType ¶
type EncryptionType uint8
EncryptionType encryption algorithm type
const ( EncryptionNone EncryptionType = 0 EncryptionAES256 EncryptionType = 1 )
type PageCipher ¶
type PageCipher struct {
// contains filtered or unexported fields
}
PageCipher holds encKey and macKey for page-level encryption. Thread-safe: instance is immutable after construction.
func NewPageCipher ¶
func NewPageCipher(encKey, macKey []byte) (*PageCipher, error)
func (*PageCipher) Clear ¶ added in v1.2.1
func (pc *PageCipher) Clear()
Clear 安全擦除内存中的密钥材料,防止密钥在堆内存中残留。 调用后 PageCipher 实例不可再用于加解密操作。
func (*PageCipher) DecryptBlob ¶
func (pc *PageCipher) DecryptBlob(ciphertext []byte, id uint32) ([]byte, error)
DecryptBlob decrypts variable-length data and removes PKCS7 padding.
func (*PageCipher) DecryptPage ¶
func (pc *PageCipher) DecryptPage(data []byte, pageID uint32) ([]byte, error)
DecryptPage decrypts a page (including HMAC tag), handling both old and new formats.
Detection strategy:
- Try new format: extract nonce from data[:NonceSize], verify HMAC over data[NonceSize:len(data)-HMACSize], use nonce-XOR'd IV.
- If HMAC fails, fall back to old format: HMAC over data[:len(data)-HMACSize], use pageID-only deterministic IV.
Returns plaintext (exactly pageSize bytes).
func (*PageCipher) DecryptVerificationBlock ¶
func (pc *PageCipher) DecryptVerificationBlock(data []byte) ([]byte, error)
DecryptVerificationBlock decrypts the verification block. M3 修复:自动检测格式。
- 旧格式(16 字节):零 IV AES-CBC 解密(版本 1/2 数据库)
- 新格式(24 字节):nonce(8B) || ciphertext(16B)(版本 3 数据库)
func (*PageCipher) EncryptBlob ¶
func (pc *PageCipher) EncryptBlob(plaintext []byte, id uint32) ([]byte, error)
EncryptBlob encrypts variable-length data with PKCS7 padding.
func (*PageCipher) EncryptPage ¶
func (pc *PageCipher) EncryptPage(plaintext []byte, pageID uint32) ([]byte, error)
EncryptPage encrypts a page of plaintext using AES-256-CBC with a random nonce. Format (new): nonce(8B) || ciphertext(pageSize) || HMAC(16B) The nonce is XOR'd into the first 8 bytes of deriveIV(pageID) to produce a non-deterministic per-encryption IV. Identical plaintext pages no longer produce identical ciphertext.
HMAC is computed over ciphertext only (not the nonce prefix), matching the old format's HMAC range for backward compatibility.
func (*PageCipher) EncryptVerificationBlock ¶
func (pc *PageCipher) EncryptVerificationBlock() ([]byte, error)
EncryptVerificationBlock encrypts the 16-byte verification block. M3 修复:使用随机 nonce 替代零 IV,防止已知明文攻击削弱密钥暴力破解抗性。 格式: nonce(8B) || ciphertext(16B),nonce XOR'd into deriveIV(0)。