mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-05-19 18:58:03 +02:00
410bffe643
* refactor: naming cleanup across all packages
214 lines
5.3 KiB
Go
214 lines
5.3 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/des"
|
|
"crypto/hmac"
|
|
"crypto/sha1"
|
|
"crypto/sha256"
|
|
"encoding/asn1"
|
|
)
|
|
|
|
const des3KeySize = 24 // 3DES uses 24-byte (192-bit) keys
|
|
|
|
// ASN1PBE represents a Password-Based Encryption structure from Firefox's NSS.
|
|
// The key parameter semantics vary by implementation:
|
|
// - privateKeyPBE / passwordCheckPBE: key is the global salt used for key derivation
|
|
// - credentialPBE: key is the already-derived master key
|
|
type ASN1PBE interface {
|
|
Decrypt(key []byte) ([]byte, error)
|
|
Encrypt(key, plaintext []byte) ([]byte, error)
|
|
}
|
|
|
|
func NewASN1PBE(b []byte) (pbe ASN1PBE, err error) {
|
|
var (
|
|
nss privateKeyPBE
|
|
meta passwordCheckPBE
|
|
login credentialPBE
|
|
)
|
|
if _, err := asn1.Unmarshal(b, &nss); err == nil {
|
|
return nss, nil
|
|
}
|
|
if _, err := asn1.Unmarshal(b, &meta); err == nil {
|
|
return meta, nil
|
|
}
|
|
if _, err := asn1.Unmarshal(b, &login); err == nil {
|
|
return login, nil
|
|
}
|
|
return nil, errDecodeASN1
|
|
}
|
|
|
|
// privateKeyPBE Struct
|
|
//
|
|
// SEQUENCE (2 elem)
|
|
// OBJECT IDENTIFIER
|
|
// SEQUENCE (2 elem)
|
|
// OCTET STRING (20 byte)
|
|
// INTEGER 1
|
|
// OCTET STRING (16 byte)
|
|
type privateKeyPBE struct {
|
|
AlgoAttr struct {
|
|
asn1.ObjectIdentifier
|
|
SaltAttr struct {
|
|
EntrySalt []byte
|
|
KeyLen int
|
|
}
|
|
}
|
|
Encrypted []byte
|
|
}
|
|
|
|
func (n privateKeyPBE) Decrypt(globalSalt []byte) ([]byte, error) {
|
|
key, iv := n.deriveKeyAndIV(globalSalt)
|
|
return DES3Decrypt(key, iv, n.Encrypted)
|
|
}
|
|
|
|
func (n privateKeyPBE) Encrypt(globalSalt, plaintext []byte) ([]byte, error) {
|
|
key, iv := n.deriveKeyAndIV(globalSalt)
|
|
return DES3Encrypt(key, iv, plaintext)
|
|
}
|
|
|
|
// deriveKeyAndIV implements NSS PBE-SHA1-3DES key derivation.
|
|
// Reference: https://searchfox.org/mozilla-central/source/security/nss/lib/softoken/lowpbe.c
|
|
//
|
|
// Derivation steps:
|
|
//
|
|
// hp = SHA1(globalSalt)
|
|
// ck = SHA1(hp || entrySalt)
|
|
// hmac1 = HMAC-SHA1(ck, paddedSalt)
|
|
// k1 = HMAC-SHA1(ck, paddedSalt || entrySalt)
|
|
// k2 = HMAC-SHA1(ck, hmac1 || entrySalt)
|
|
// dk = k1 || k2 (40 bytes)
|
|
// key = dk[:24], iv = dk[32:]
|
|
func (n privateKeyPBE) deriveKeyAndIV(globalSalt []byte) ([]byte, []byte) {
|
|
entrySalt := n.AlgoAttr.SaltAttr.EntrySalt
|
|
hp := sha1.Sum(globalSalt)
|
|
ck := sha1.Sum(append(hp[:], entrySalt...))
|
|
paddedSalt := paddingZero(entrySalt, 20)
|
|
|
|
hmac1 := hmac.New(sha1.New, ck[:])
|
|
hmac1.Write(paddedSalt)
|
|
|
|
k1 := hmac.New(sha1.New, ck[:])
|
|
k1.Write(append(paddedSalt, entrySalt...))
|
|
|
|
k2 := hmac.New(sha1.New, ck[:])
|
|
k2.Write(append(hmac1.Sum(nil), entrySalt...))
|
|
|
|
dk := append(k1.Sum(nil), k2.Sum(nil)...)
|
|
return dk[:24], dk[len(dk)-8:]
|
|
}
|
|
|
|
// MetaPBE Struct
|
|
//
|
|
// SEQUENCE (2 elem)
|
|
// OBJECT IDENTIFIER
|
|
// SEQUENCE (2 elem)
|
|
// SEQUENCE (2 elem)
|
|
// OBJECT IDENTIFIER
|
|
// SEQUENCE (4 elem)
|
|
// OCTET STRING (32 byte)
|
|
// INTEGER 1
|
|
// INTEGER 32
|
|
// SEQUENCE (1 elem)
|
|
// OBJECT IDENTIFIER
|
|
// SEQUENCE (2 elem)
|
|
// OBJECT IDENTIFIER
|
|
// OCTET STRING (14 byte)
|
|
// OCTET STRING (16 byte)
|
|
type passwordCheckPBE struct {
|
|
AlgoAttr algoAttr
|
|
Encrypted []byte
|
|
}
|
|
|
|
type algoAttr struct {
|
|
asn1.ObjectIdentifier
|
|
KDFParams struct {
|
|
PBKDF2 struct {
|
|
asn1.ObjectIdentifier
|
|
SaltAttr saltAttr
|
|
}
|
|
IVData ivAttr
|
|
}
|
|
}
|
|
|
|
type ivAttr struct {
|
|
asn1.ObjectIdentifier
|
|
IV []byte
|
|
}
|
|
|
|
type saltAttr struct {
|
|
EntrySalt []byte
|
|
IterationCount int
|
|
KeySize int
|
|
Algorithm struct {
|
|
asn1.ObjectIdentifier
|
|
}
|
|
}
|
|
|
|
func (m passwordCheckPBE) Decrypt(globalSalt []byte) ([]byte, error) {
|
|
key, iv := m.deriveKeyAndIV(globalSalt)
|
|
return AESCBCDecrypt(key, iv, m.Encrypted)
|
|
}
|
|
|
|
func (m passwordCheckPBE) Encrypt(globalSalt, plaintext []byte) ([]byte, error) {
|
|
key, iv := m.deriveKeyAndIV(globalSalt)
|
|
return AESCBCEncrypt(key, iv, plaintext)
|
|
}
|
|
|
|
func (m passwordCheckPBE) deriveKeyAndIV(globalSalt []byte) ([]byte, []byte) {
|
|
password := sha1.Sum(globalSalt)
|
|
|
|
params := m.AlgoAttr.KDFParams.PBKDF2.SaltAttr
|
|
key := PBKDF2Key(password[:], params.EntrySalt, params.IterationCount, params.KeySize, sha256.New)
|
|
|
|
// Firefox stores the IV with its ASN.1 OCTET STRING header (tag=0x04, length=0x0E).
|
|
// The full 16-byte IV = [0x04, 0x0E] + 14-byte IV value from the parsed structure.
|
|
iv := append([]byte{0x04, 0x0E}, m.AlgoAttr.KDFParams.IVData.IV...)
|
|
return key, iv
|
|
}
|
|
|
|
// credentialPBE Struct
|
|
//
|
|
// OCTET STRING (16 byte)
|
|
// SEQUENCE (2 elem)
|
|
// OBJECT IDENTIFIER
|
|
// OCTET STRING (8 byte)
|
|
// OCTET STRING (16 byte)
|
|
type credentialPBE struct {
|
|
KeyCheck []byte
|
|
Algo struct {
|
|
asn1.ObjectIdentifier
|
|
IV []byte
|
|
}
|
|
Encrypted []byte
|
|
}
|
|
|
|
func (l credentialPBE) Decrypt(masterKey []byte) ([]byte, error) {
|
|
key, iv := l.deriveKeyAndIV(masterKey)
|
|
// The cipher is inferred from IV length (avoids fragile OID checks):
|
|
switch len(iv) {
|
|
case des.BlockSize: // 8: 3DES-CBC (legacy Firefox)
|
|
return DES3Decrypt(key[:des3KeySize], iv, l.Encrypted)
|
|
case aes.BlockSize: // 16: AES-256-CBC (Firefox 144+)
|
|
return AESCBCDecrypt(key, iv, l.Encrypted)
|
|
default:
|
|
return nil, errUnsupportedIVLen
|
|
}
|
|
}
|
|
|
|
func (l credentialPBE) Encrypt(masterKey, plaintext []byte) ([]byte, error) {
|
|
key, iv := l.deriveKeyAndIV(masterKey)
|
|
switch len(iv) {
|
|
case des.BlockSize:
|
|
return DES3Encrypt(key[:des3KeySize], iv, plaintext)
|
|
case aes.BlockSize:
|
|
return AESCBCEncrypt(key, iv, plaintext)
|
|
default:
|
|
return nil, errUnsupportedIVLen
|
|
}
|
|
}
|
|
|
|
func (l credentialPBE) deriveKeyAndIV(masterKey []byte) ([]byte, []byte) {
|
|
return masterKey, l.Algo.IV
|
|
}
|