-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate_vectors.py
More file actions
109 lines (89 loc) · 3.23 KB
/
generate_vectors.py
File metadata and controls
109 lines (89 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import base64
import hashlib
import hmac
import json
from pathlib import Path
APP_SECRET = "af_test_secret_2026_reference"
SIG_KEY = "af_test_sig_key_2026_reference_0123456789abcdef"
NONCE = "0123456789abcdeffedcba9876543210"
SESSION_SIGNING_SECRET = "authforge-dev-session-signing-secret-rotate-before-production"
EXPIRES_IN = 1740433200
TIMESTAMP = 1740429600
APP_ID = "test-app"
LICENSE_KEY = "test-key"
HWID = "testhwid"
def _b64url_no_pad(data: bytes) -> str:
return base64.urlsafe_b64encode(data).decode("ascii").rstrip("=")
def _build_session_token() -> str:
body = {
"appId": APP_ID,
"licenseKey": LICENSE_KEY,
"hwid": HWID,
"sigKey": SIG_KEY,
"expiresIn": EXPIRES_IN,
}
body_json = json.dumps(body, separators=(",", ":")).encode("utf-8")
body_b64 = _b64url_no_pad(body_json)
digest = hmac.new(
SESSION_SIGNING_SECRET.encode("utf-8"),
body_b64.encode("utf-8"),
hashlib.sha256,
).digest()
sig_b64 = _b64url_no_pad(digest)
return f"{body_b64}.{sig_b64}"
def _build_payload_b64() -> str:
payload_obj = {
"sessionToken": _build_session_token(),
"timestamp": TIMESTAMP,
"expiresIn": EXPIRES_IN,
"nonce": NONCE,
}
payload_json = json.dumps(payload_obj, separators=(",", ":")).encode("utf-8")
return base64.b64encode(payload_json).decode("ascii")
def _hmac_hex(key: bytes, message: str) -> str:
return hmac.new(key, message.encode("utf-8"), hashlib.sha256).hexdigest()
def _sha256_hex(value: str) -> str:
return hashlib.sha256(value.encode("utf-8")).hexdigest()
def main() -> None:
payload = _build_payload_b64()
validate_key = hashlib.sha256(f"{APP_SECRET}{NONCE}".encode("utf-8")).digest()
validate_sig = _hmac_hex(validate_key, payload)
heartbeat_key = hashlib.sha256(f"{SIG_KEY}{NONCE}".encode("utf-8")).digest()
heartbeat_sig = _hmac_hex(heartbeat_key, payload)
vectors = {
"validate": {
"algorithm": {
"keyDerivation": "SHA256(appSecret + nonce)",
"signature": "HMAC-SHA256(raw_base64_payload_string, derivedKey)",
},
"inputs": {
"appSecret": APP_SECRET,
"nonce": NONCE,
"payload": payload,
},
"outputs": {
"derivedKeyHex": validate_key.hex(),
"signatureHex": validate_sig,
},
},
"heartbeat": {
"algorithm": {
"keyDerivation": "SHA256(sigKey + nonce)",
"signature": "HMAC-SHA256(raw_base64_payload_string, derivedKey)",
},
"inputs": {
"sigKey": SIG_KEY,
"nonce": NONCE,
"payload": payload,
},
"outputs": {
"derivedKeyHex": heartbeat_key.hex(),
"signatureHex": heartbeat_sig,
},
},
}
output_path = Path(__file__).with_name("test_vectors.json")
output_path.write_text(json.dumps(vectors, indent=2), encoding="utf-8")
print(str(output_path))
if __name__ == "__main__":
main()