Skip to content

Commit 7e99340

Browse files
committed
Initial commit
0 parents  commit 7e99340

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
This is an open source reimplementation of `R2RLIVE.dll` by Team R2R.
2+
3+
Like `R2RLIVE.dll`, this script uses Team R2R's signing key only.
4+
5+
This script is not the result of reverse engineering Ableton Live, and the output of this script **will not** circumvent the protection on an unmodified copy of Ableton Live.

kg.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import re
2+
import sys
3+
from random import randint
4+
from typing import List
5+
6+
from cryptography.hazmat.backends import default_backend
7+
from cryptography.hazmat.primitives.asymmetric import dsa
8+
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
9+
from cryptography.hazmat.primitives.hashes import SHA1
10+
11+
12+
def construct_key(*, p, q, g, y, x) -> dsa.DSAPrivateKey:
13+
params = dsa.DSAParameterNumbers(p, q, g)
14+
pub = dsa.DSAPublicNumbers(y, params)
15+
priv = dsa.DSAPrivateNumbers(x, pub)
16+
return priv.private_key(backend=default_backend())
17+
18+
19+
def sign(k: dsa.DSAPrivateKey, m: str) -> str:
20+
"""P1363 format sig over m as a string of hex digits"""
21+
assert k.key_size == 1024
22+
sig = k.sign(m.encode(), SHA1())
23+
r, s = decode_dss_signature(sig)
24+
return "{:040X}{:040X}".format(r, s)
25+
26+
27+
def fix_group_checksum(group_number: int, n: int) -> int:
28+
checksum = n >> 4 & 0xf ^ \
29+
n >> 5 & 0x8 ^ \
30+
n >> 9 & 0x7 ^ \
31+
n >> 11 & 0xe ^ \
32+
n >> 15 & 0x1 ^ \
33+
group_number
34+
return n & 0xfff0 | checksum
35+
36+
37+
def overall_checksum(groups: List[int]) -> int:
38+
r = 0
39+
for i in range(20):
40+
g, digit = divmod(i, 4)
41+
v = groups[g] >> (digit * 8) & 0xff
42+
# v is lowbyte, highbyte, 0, 0 in turn for each group
43+
r ^= v << 8
44+
for _ in range(8):
45+
r <<= 1
46+
if r & 0x10000:
47+
r ^= 0x8005
48+
return r & 0xffff
49+
50+
51+
def random_serial():
52+
"""
53+
3xxc-xxxc-xxxc-xxxc-xxxc-dddd
54+
x is random
55+
c is a checksum over each group
56+
d is a checksum over all groups
57+
"""
58+
groups = [randint(0x3000, 0x3fff),
59+
randint(0x0000, 0xffff),
60+
randint(0x0000, 0xffff),
61+
randint(0x0000, 0xffff),
62+
randint(0x0000, 0xffff)]
63+
for i in range(5):
64+
groups[i] = fix_group_checksum(i, groups[i])
65+
d = overall_checksum(groups)
66+
return "{:04X}-{:04X}-{:04X}-{:04X}-{:04X}-{:04X}".format(*groups, d)
67+
68+
69+
def generate_single(k: dsa.DSAPrivateKey, id1: int, id2: int, hwid: str) -> str:
70+
f = "{},{:02X},{:02X},Standard,{}"
71+
serial = random_serial()
72+
msg = f.format(serial, id1, id2, hwid)
73+
sig = sign(k, msg)
74+
return f.format(serial, id1, id2, sig)
75+
76+
77+
def generate_all(k: dsa.DSAPrivateKey, hwid: str) -> str:
78+
yield generate_single(k, 0x0, 0xa0, hwid)
79+
for i in range(0x40, 0xff + 1):
80+
yield generate_single(k, i, 0x10, hwid)
81+
for i in range(0x8000, 0x80ff + 1):
82+
yield generate_single(k, i, 0x10, hwid)
83+
84+
85+
team_r2r_key = construct_key(
86+
p=0xbab5a10970f083e266a1252897daac1d67374712e79d3df1bc8c08a3493c6aa9a2ff33be4513d8b6767ab6aae2af6cc9107976fa75fee134e8b7be03d78cc64e089c845207d306a6035f172c5b750275f00bd3ca2331b8a59d54fe79393854dd884b8d334d553b38bc5e886c0a2dd0e4ec32f7d88de1a7c9df5c424ee7b1ce6d,
87+
q=0xc37be90e3f8e64e03a42ca8d68ad5c83eb47d3a9,
88+
g=0xa33c8737f42e2516a1525544e611d71295805ced94d260d5777db976f6721f52479158e2477efb0ea6ff30d34d15b23669f0967d29a2c746288ee42c8d91fe4dbe79a73ee8831251a3566864858e589adcd41c3863ea118fbbcdf34bd64ef0e7ae20b00192709a8346c816b54a51d804a6e06fce1da4b043c2b5270d4e441622,
89+
y=0x33fd12fd459fe6c5c1bc0991e915f8bf49997716bde5c3bdf9a096bdcbf7a425ef6a495683cc84f3dafab7a1d5cf9f377fda84c042e47e7c608298c6917a3caab40b3c6262559fe699091c5bb6ac8de01f0a9f887c739ffa3a1a858000f85a1811ec33a2190063341e8c20aba068b90383f8ca27d30aa89adf40de9ce735dedb,
90+
x=0xc369ea757b46484d1df3819cc4183f6f9a9bcf3c
91+
)
92+
93+
assert len(sys.argv) == 2, "Expected hardware ID as command line argument"
94+
hwid = sys.argv[1].upper()
95+
assert re.fullmatch(r"([0-9A-F]{4}-){5}[0-9A-F]{4}", hwid), "Expected hardware ID like 1111-1111-1111-1111-1111-1111"
96+
97+
for line in generate_all(team_r2r_key, hwid):
98+
print(line)

0 commit comments

Comments
 (0)