Add AlphaRne rgtool keygen

See https://www.eevblog.com/forum/testgear/hacking-the-hdo1khdo4k-rigol-12-bit-scope/msg4503478/#msg4503478

Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
This commit is contained in:
Olliver Schinagl 2022-11-10 16:16:46 +01:00
parent 31cf51566b
commit 7cc9334893
No known key found for this signature in database
GPG Key ID: 96E1A3A6C9044763
2 changed files with 243 additions and 0 deletions

16
README.md Normal file
View File

@ -0,0 +1,16 @@
# Rigol HDO-series license generator
* Obtain the IP address of the scope
* Connect to the scope using the Android Debug Bridge `adb connect <IP of scope>:55555`
* Download the unique key from the scope `adb pull /rigol/data/Key.data`
* Generate the license key using the rgtool program on the Key file `go run ./rgtool.go`
* Insert generated codes via SCPI interface on the website on the scope (`http://<IP of scope>`)
When not wanting to install adb or go, docker could also be used instead.
```sh
docker run --rm -it -v $(pwd):/workdir -w /workdir alpine \
/bin/sh -c 'apk add android-tools && adb connect <IP of scope>:55555 && adb pull /rigol/data/Key.data'
```
```sh
docker run --rm -it -v $(pwd):/workdir -w /workdir golang go run ./rgtool.go
```

227
rgtool.go Normal file
View File

@ -0,0 +1,227 @@
package main
import (
"bytes"
"crypto/aes"
"encoding/binary"
"errors"
"flag"
"fmt"
"io/ioutil"
"os/user"
"path/filepath"
)
/*
0 maybe device ID, not needed to work
1
2 lic name string
3 lic Type "0"
4 lic time "0"
5
*/
var keyFile string
var deviceId string
func initCmdline() {
flag.StringVar(&keyFile, "k", "Key.data", "key file")
flag.StringVar(&deviceId, "id", "HDO4XXXXXX", "devide Id")
flag.Parse()
}
func Expand(path string) string {
if len(path) == 0 || path[0] != '~' {
return path
}
usr, err := user.Current()
if err != nil {
return path
}
return filepath.Join(usr.HomeDir, path[1:])
}
const delta = 0x9E3779B9
func mx(sum uint32, y uint32, z uint32, p uint32, e uint32, k []uint32) uint32 {
return ((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum ^ y) + (k[p&3^e] ^ z))
}
func fixk(k []uint32) []uint32 {
if len(k) < 4 {
key := make([]uint32, 4)
copy(key, k)
return key
}
return k
}
func XXTeaEncrypt(v []uint32, k []uint32) []uint32 {
length := uint32(len(v))
n := length - 1
k = fixk(k)
var y, z, sum, e, p, q uint32
z = v[n]
sum = 0
for q = 6 + 52/length; q > 0; q-- {
sum += delta
e = sum >> 2 & 3
for p = 0; p < n; p++ {
y = v[p+1]
v[p] += mx(sum, y, z, p, e, k)
z = v[p]
}
y = v[0]
v[n] += mx(sum, y, z, p, e, k)
z = v[n]
}
return v
}
func XXTeaDecrypt(v []uint32, k []uint32) []uint32 {
length := uint32(len(v))
n := length - 1
k = fixk(k)
var y, z, sum, e, p, q uint32
y = v[0]
q = 6 + 52/length
for sum = q * delta; sum != 0; sum -= delta {
e = sum >> 2 & 3
for p = n; p > 0; p-- {
z = v[p-1]
v[p] -= mx(sum, y, z, p, e, k)
y = v[p]
}
z = v[n]
v[0] -= mx(sum, y, z, p, e, k)
y = v[0]
}
return v
}
func HexString(data []byte) string {
var buf bytes.Buffer
for i := 0; i < len(data)-1; i++ {
buf.WriteString(fmt.Sprintf("%02X ", data[i]))
}
buf.WriteString(fmt.Sprintf("%02X", data[len(data)-1]))
return buf.String()
}
func HexStringS(data []byte, sep string) string {
var buf bytes.Buffer
for i := 0; i < len(data)-1; i++ {
buf.WriteString(fmt.Sprintf("%02X%s", data[i], sep))
}
buf.WriteString(fmt.Sprintf("%02X", data[len(data)-1]))
return buf.String()
}
func HexStringLsb(data []byte, sep string) string {
var buf bytes.Buffer
for i := 0; i < len(data)-1; i++ {
buf.WriteString(fmt.Sprintf("%02x%s", (data[i]<<4)|(data[i]>>4), sep))
}
t := data[len(data)-1]
buf.WriteString(fmt.Sprintf("%02x", (t<<4)|(t>>4)))
return buf.String()
}
func decodeDefaultXXTEA(data []byte) []byte {
k := []uint32{0x03920001, 0x08410841, 0x18C32104, 0x318639C7}
N := len(data)
u32 := make([]uint32, N>>2)
for i, _ := range u32 {
u32[i] = binary.LittleEndian.Uint32(data[i*4:])
}
u32d := XXTeaDecrypt(u32, k)
res := make([]uint8, N)
for i, v := range u32d {
binary.LittleEndian.PutUint32(res[i*4:], v)
}
return res
}
func EncryptLicenseString(key []uint8, str string) (string, error) {
block, err := aes.NewCipher(key)
if nil != err {
return "", err
}
x := make([]uint8, 48)
copy(x, []uint8(str))
block.Encrypt(x, x)
block.Encrypt(x[0x10:], x[0x10:])
block.Encrypt(x[0x20:], x[0x20:])
return HexStringLsb(x, ""), nil
}
func MakeLicense(key []uint8, deviceId, feature string) string {
s := fmt.Sprintf("%s#0#%s#4#0#0", deviceId, feature)
res, err := EncryptLicenseString(key, s)
if nil != err {
return ""
}
return fmt.Sprintf("HDO4000-%s@%s", feature, res)
}
func LoadKeys() ([]uint8, error) {
data, err := ioutil.ReadFile(Expand(keyFile))
if nil != err {
return nil, err
}
dd := decodeDefaultXXTEA(data)
i := bytes.Index(dd, []uint8(";"))
if -1 == i {
return nil, errors.New("key format error")
}
fmt.Printf("Key: %v\n", string(dd))
return dd[i+1:], nil
}
// BND
// MSO
// COMP
// EMBD
// AUTO
// FLEX
// AUDIO
// AERO
// ARINC
// DG
// JITTER
// EYE
// RTSA
// CM_USB
// CM_ENET
// CM_IPI
// CM_HDMI
// PWR
// UPA
// RLU
// BODE
// BW7T10
// BW7T20
// BW100T20
// BW2T4
// BW2T8
// BW4T8
// COUNT
// UNKNOWN
var options []string = []string{"EMBD", "AUTO", "BW2T8", "COMP", "AERO", "FLEX", "AUDIO", "RLU", "UPA"}
func main() {
initCmdline()
k, err := LoadKeys()
if nil != err {
fmt.Printf("error %v\n", err)
return
}
fmt.Printf("Generating options for %s\n", deviceId)
for _, o := range options {
lic := MakeLicense(k[0:32], deviceId, o)
fmt.Printf(":SYST:OPT:INST %v\n", lic)
}
}