56 lines
1.1 KiB
Go
56 lines
1.1 KiB
Go
package kgm
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"fmt"
|
|
|
|
"unlock-music.dev/cli/algo/common"
|
|
)
|
|
|
|
// kgmCryptoV3 is kgm file crypto v3
|
|
type kgmCryptoV3 struct {
|
|
slotBox []byte
|
|
fileBox []byte
|
|
}
|
|
|
|
var kgmV3Slot2Key = map[uint32][]byte{
|
|
1: {0x6C, 0x2C, 0x2F, 0x27},
|
|
}
|
|
|
|
func newKgmCryptoV3(header *header) (common.StreamDecoder, error) {
|
|
c := &kgmCryptoV3{}
|
|
|
|
slotKey, ok := kgmV3Slot2Key[header.CryptoSlot]
|
|
if !ok {
|
|
return nil, fmt.Errorf("kgm3: unknown crypto slot %d", header.CryptoSlot)
|
|
}
|
|
c.slotBox = kugouMD5(slotKey)
|
|
|
|
c.fileBox = append(kugouMD5(header.CryptoKey), 0x6b)
|
|
|
|
return c, nil
|
|
}
|
|
|
|
func (d *kgmCryptoV3) Decrypt(b []byte, offset int) {
|
|
for i := 0; i < len(b); i++ {
|
|
b[i] ^= d.fileBox[(offset+i)%len(d.fileBox)]
|
|
b[i] ^= b[i] << 4
|
|
b[i] ^= d.slotBox[(offset+i)%len(d.slotBox)]
|
|
b[i] ^= xorCollapseUint32(uint32(offset + i))
|
|
}
|
|
}
|
|
|
|
func xorCollapseUint32(i uint32) byte {
|
|
return byte(i) ^ byte(i>>8) ^ byte(i>>16) ^ byte(i>>24)
|
|
}
|
|
|
|
func kugouMD5(b []byte) []byte {
|
|
digest := md5.Sum(b)
|
|
ret := make([]byte, 16)
|
|
for i := 0; i < md5.Size; i += 2 {
|
|
ret[i] = digest[14-i]
|
|
ret[i+1] = digest[14-i+1]
|
|
}
|
|
return ret
|
|
}
|