mirror of
https://git.um-react.app/um/cli.git
synced 2025-11-28 03:33:02 +00:00
refactor: use kgm crypto from parakeet-rs
chore: update deps
This commit is contained in:
@@ -2,27 +2,24 @@ package kgm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/unlock-music/cli/algo/common"
|
||||
)
|
||||
|
||||
var (
|
||||
vprHeader = []byte{
|
||||
0x05, 0x28, 0xBC, 0x96, 0xE9, 0xE4, 0x5A, 0x43,
|
||||
0x91, 0xAA, 0xBD, 0xD0, 0x7A, 0xF5, 0x36, 0x31}
|
||||
kgmHeader = []byte{
|
||||
0x7C, 0xD5, 0x32, 0xEB, 0x86, 0x02, 0x7F, 0x4B,
|
||||
0xA8, 0xAF, 0xA6, 0x8E, 0x0F, 0xFF, 0x99, 0x14}
|
||||
ErrKgmMagicHeader = errors.New("kgm/vpr magic header not matched")
|
||||
)
|
||||
|
||||
type Decoder struct {
|
||||
file []byte
|
||||
key []byte
|
||||
maskFunc func(int) byte
|
||||
audio []byte
|
||||
header Header
|
||||
initializer kgmCryptoInitializer
|
||||
|
||||
file []byte
|
||||
audio []byte
|
||||
}
|
||||
|
||||
type kgmCryptoInitializer func(header *Header, body io.Reader) (io.Reader, error)
|
||||
|
||||
var kgmCryptoInitializers = map[uint32]kgmCryptoInitializer{
|
||||
3: newKgmCryptoV3,
|
||||
}
|
||||
|
||||
func NewDecoder(file []byte) common.Decoder {
|
||||
@@ -44,31 +41,34 @@ func (d *Decoder) GetMeta() common.Meta {
|
||||
}
|
||||
|
||||
func (d *Decoder) Validate() error {
|
||||
if bytes.Equal(kgmHeader, d.file[:len(kgmHeader)]) {
|
||||
d.maskFunc = getKgmMask
|
||||
} else if bytes.Equal(vprHeader, d.file[:len(vprHeader)]) {
|
||||
d.maskFunc = getVprMask
|
||||
} else {
|
||||
return ErrKgmMagicHeader
|
||||
if err := d.header.FromBytes(d.file); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO; validate crypto version
|
||||
|
||||
var ok bool
|
||||
d.initializer, ok = kgmCryptoInitializers[d.header.CryptoVersion]
|
||||
if !ok {
|
||||
return fmt.Errorf("kgm: unsupported crypto version %d", d.header.CryptoVersion)
|
||||
}
|
||||
|
||||
d.key = d.file[0x1c:0x2c]
|
||||
d.key = append(d.key, 0x00)
|
||||
_ = d.file[0x2c:0x3c] //todo: key2
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) Decode() error {
|
||||
headerLen := binary.LittleEndian.Uint32(d.file[0x10:0x14])
|
||||
d.audio = d.file[headerLen:]
|
||||
d.audio = d.file[d.header.AudioOffset:]
|
||||
|
||||
for i := 0; i < len(d.audio); i++ {
|
||||
med8 := d.audio[i] ^ d.key[i%17] ^ d.maskFunc(i)
|
||||
d.audio[i] = med8 ^ (med8&0xf)<<4
|
||||
r, err := d.initializer(&d.header, bytes.NewReader(d.audio))
|
||||
if err != nil {
|
||||
return fmt.Errorf("kgm: failed to initialize crypto: %w", err)
|
||||
}
|
||||
d.audio, err = io.ReadAll(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("kgm: failed to decrypt audio: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Kugou
|
||||
common.RegisterDecoder("kgm", false, NewDecoder)
|
||||
|
||||
Reference in New Issue
Block a user