HackBrowserData/crypto/asn1pbe.go

193 lines
4.3 KiB
Go

package crypto
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"encoding/asn1"
"errors"
)
type ASN1PBE interface {
Decrypt(globalSalt []byte) ([]byte, error)
Encrypt(globalSalt, plaintext []byte) ([]byte, error)
}
func NewASN1PBE(b []byte) (pbe ASN1PBE, err error) {
var (
nss nssPBE
meta metaPBE
login loginPBE
)
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, ErrDecodeASN1Failed
}
var ErrDecodeASN1Failed = errors.New("decode ASN1 data failed")
// nssPBE Struct
//
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER
// SEQUENCE (2 elem)
// OCTET STRING (20 byte)
// INTEGER 1
// OCTET STRING (16 byte)
type nssPBE struct {
AlgoAttr struct {
asn1.ObjectIdentifier
SaltAttr struct {
EntrySalt []byte
Len int
}
}
Encrypted []byte
}
// Decrypt decrypts the encrypted password with the global salt.
func (n nssPBE) Decrypt(globalSalt []byte) ([]byte, error) {
key, iv := n.deriveKeyAndIV(globalSalt)
return DES3Decrypt(key, iv, n.Encrypted)
}
func (n nssPBE) Encrypt(globalSalt, plaintext []byte) ([]byte, error) {
key, iv := n.deriveKeyAndIV(globalSalt)
return DES3Encrypt(key, iv, plaintext)
}
// deriveKeyAndIV derives the key and initialization vector (IV)
// from the global salt and entry salt.
func (n nssPBE) deriveKeyAndIV(globalSalt []byte) ([]byte, []byte) {
salt := n.AlgoAttr.SaltAttr.EntrySalt
hashPrefix := sha1.Sum(globalSalt)
compositeHash := sha1.Sum(append(hashPrefix[:], salt...))
paddedEntrySalt := paddingZero(salt, 20)
hmacProcessor := hmac.New(sha1.New, compositeHash[:])
hmacProcessor.Write(paddedEntrySalt)
paddedEntrySalt = append(paddedEntrySalt, salt...)
keyComponent1 := hmac.New(sha1.New, compositeHash[:])
keyComponent1.Write(paddedEntrySalt)
hmacWithSalt := append(hmacProcessor.Sum(nil), salt...)
keyComponent2 := hmac.New(sha1.New, compositeHash[:])
keyComponent2.Write(hmacWithSalt)
key := append(keyComponent1.Sum(nil), keyComponent2.Sum(nil)...)
iv := key[len(key)-8:]
return key[:24], iv
}
// 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 metaPBE struct {
AlgoAttr algoAttr
Encrypted []byte
}
type algoAttr struct {
asn1.ObjectIdentifier
Data struct {
Data struct {
asn1.ObjectIdentifier
SlatAttr slatAttr
}
IVData ivAttr
}
}
type ivAttr struct {
asn1.ObjectIdentifier
IV []byte
}
type slatAttr struct {
EntrySalt []byte
IterationCount int
KeySize int
Algorithm struct {
asn1.ObjectIdentifier
}
}
func (m metaPBE) Decrypt(globalSalt []byte) ([]byte, error) {
key, iv := m.deriveKeyAndIV(globalSalt)
return AES128CBCDecrypt(key, iv, m.Encrypted)
}
func (m metaPBE) Encrypt(globalSalt, plaintext []byte) ([]byte, error) {
key, iv := m.deriveKeyAndIV(globalSalt)
return AES128CBCEncrypt(key, iv, plaintext)
}
func (m metaPBE) deriveKeyAndIV(globalSalt []byte) ([]byte, []byte) {
password := sha1.Sum(globalSalt)
salt := m.AlgoAttr.Data.Data.SlatAttr.EntrySalt
iter := m.AlgoAttr.Data.Data.SlatAttr.IterationCount
keyLen := m.AlgoAttr.Data.Data.SlatAttr.KeySize
key := PBKDF2Key(password[:], salt, iter, keyLen, sha256.New)
iv := append([]byte{4, 14}, m.AlgoAttr.Data.IVData.IV...)
return key, iv
}
// loginPBE Struct
//
// OCTET STRING (16 byte)
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER
// OCTET STRING (8 byte)
// OCTET STRING (16 byte)
type loginPBE struct {
CipherText []byte
Data struct {
asn1.ObjectIdentifier
IV []byte
}
Encrypted []byte
}
func (l loginPBE) Decrypt(globalSalt []byte) ([]byte, error) {
key, iv := l.deriveKeyAndIV(globalSalt)
return DES3Decrypt(key, iv, l.Encrypted)
}
func (l loginPBE) Encrypt(globalSalt, plaintext []byte) ([]byte, error) {
key, iv := l.deriveKeyAndIV(globalSalt)
return DES3Encrypt(key, iv, plaintext)
}
func (l loginPBE) deriveKeyAndIV(globalSalt []byte) ([]byte, []byte) {
return globalSalt, l.Data.IV
}