kgm_header.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package kgm
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "io"
  8. )
  9. var (
  10. vprHeader = []byte{
  11. 0x05, 0x28, 0xBC, 0x96, 0xE9, 0xE4, 0x5A, 0x43,
  12. 0x91, 0xAA, 0xBD, 0xD0, 0x7A, 0xF5, 0x36, 0x31,
  13. }
  14. kgmHeader = []byte{
  15. 0x7C, 0xD5, 0x32, 0xEB, 0x86, 0x02, 0x7F, 0x4B,
  16. 0xA8, 0xAF, 0xA6, 0x8E, 0x0F, 0xFF, 0x99, 0x14,
  17. }
  18. ErrKgmMagicHeader = errors.New("kgm magic header not matched")
  19. )
  20. // header is the header of a KGM file.
  21. type header struct {
  22. MagicHeader []byte // 0x00-0x0f: magic header
  23. AudioOffset uint32 // 0x10-0x13: offset of audio data
  24. CryptoVersion uint32 // 0x14-0x17: crypto version
  25. CryptoSlot uint32 // 0x18-0x1b: crypto key slot
  26. CryptoTestData []byte // 0x1c-0x2b: crypto test data
  27. CryptoKey []byte // 0x2c-0x3b: crypto key
  28. }
  29. func (h *header) FromFile(rd io.ReadSeeker) error {
  30. if _, err := rd.Seek(0, io.SeekStart); err != nil {
  31. return fmt.Errorf("kgm seek start: %w", err)
  32. }
  33. buf := make([]byte, 0x3c)
  34. if _, err := io.ReadFull(rd, buf); err != nil {
  35. return fmt.Errorf("kgm read header: %w", err)
  36. }
  37. return h.FromBytes(buf)
  38. }
  39. func (h *header) FromBytes(buf []byte) error {
  40. if len(buf) < 0x3c {
  41. return errors.New("invalid kgm header length")
  42. }
  43. h.MagicHeader = buf[:0x10]
  44. if !bytes.Equal(kgmHeader, h.MagicHeader) && !bytes.Equal(vprHeader, h.MagicHeader) {
  45. return ErrKgmMagicHeader
  46. }
  47. h.AudioOffset = binary.LittleEndian.Uint32(buf[0x10:0x14])
  48. h.CryptoVersion = binary.LittleEndian.Uint32(buf[0x14:0x18])
  49. h.CryptoSlot = binary.LittleEndian.Uint32(buf[0x18:0x1c])
  50. h.CryptoTestData = buf[0x1c:0x2c]
  51. h.CryptoKey = buf[0x2c:0x3c]
  52. return nil
  53. }