Created
November 10, 2023 07:32
-
-
Save KunYi/454204cc120adf929e4892ea76f032f2 to your computer and use it in GitHub Desktop.
DHI800 Oscilloscope option license generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
/* | |
the code from https://gitlab.com/riglol/rigolee/hdo-tools | |
modify for DHO800 | |
*/ | |
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", "DHO800", "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("DHO800-%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{"BW7T10", "RLU"} | |
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) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment