mirror of
https://gitlab.com/riglol/rigolee/hdo-tools.git
synced 2025-04-28 18:27:28 +09:00
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:
parent
31cf51566b
commit
7cc9334893
16
README.md
Normal file
16
README.md
Normal 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
227
rgtool.go
Normal 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)
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user