From 1d62abc9f8aaf1ced766024a829b34f75c90d6d0 Mon Sep 17 00:00:00 2001
From: Bottersnike
Date: Thu, 17 Nov 2022 18:11:21 +0000
Subject: [PATCH] Yolo encryption keys
---
images/flags/card.png | Bin 1440 -> 0 bytes
images/flags/xeai.png | Bin 4921 -> 0 bytes
templates/pages/cardid.html | 68 ++++++++++----------
templates/pages/flags.html | 7 --
templates/pages/sega/software/mxmaster.html | 2 +-
templates/pages/transport.html | 4 +-
6 files changed, 36 insertions(+), 45 deletions(-)
delete mode 100644 images/flags/card.png
delete mode 100644 images/flags/xeai.png
delete mode 100644 templates/pages/flags.html
diff --git a/images/flags/card.png b/images/flags/card.png
deleted file mode 100644
index 1ea91565d2e945d1929362b7fb3d5ffd35da6a7c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1440
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
diff --git a/templates/pages/cardid.html b/templates/pages/cardid.html
index b3f5fb6..68aafa7 100644
--- a/templates/pages/cardid.html
+++ b/templates/pages/cardid.html
@@ -10,58 +10,58 @@
cases too. It's not great code by any stretch, and it liberally uses assertions rather than proper
exceptions, but it should be a good enough starting point for your own version.
{% highlight 'python' %}
-import binascii
-from Crypto.Cipher import DES3
+ import binascii
+ from Crypto.Cipher import DES3
-KEY = b"" # Check the DES section for this
-_KEY = bytes(i * 2 for i in KEY) # Preprocess the key
+ KEY = b"?I'llB2c.YouXXXeMeHaYpy!"
+ _KEY = bytes(i * 2 for i in KEY) # Preprocess the key
-ALPHABET = "0123456789ABCDEFGHJKLMNPRSTUWXYZ"
+ ALPHABET = "0123456789ABCDEFGHJKLMNPRSTUWXYZ"
-def enc_des(uid):
+ def enc_des(uid):
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
return cipher.encrypt(uid)
-def dec_des(uid):
+ def dec_des(uid):
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
return cipher.decrypt(uid)
-def checksum(data):
-chk = sum(data[i] * (i % 3 + 1) for i in range(15))
+ def checksum(data):
+ chk = sum(data[i] * (i % 3 + 1) for i in range(15))
-while chk > 31:
+ while chk > 31:
chk = (chk >> 5) + (chk & 31)
-return chk
+ return chk
-def pack_5(data):
+ def pack_5(data):
data = "".join(f"{i:05b}" for i in data)
if len(data) % 8 != 0:
- data += "0" * (8 - (len(data) % 8))
+ data += "0" * (8 - (len(data) % 8))
return bytes(int(data[i:i+8], 2) for i in range(0, len(data), 8))
-def unpack_5(data):
+ def unpack_5(data):
data = "".join(f"{i:08b}" for i in data)
if len(data) % 5 != 0:
- data += "0" * (5 - (len(data) % 5))
+ data += "0" * (5 - (len(data) % 5))
return bytes(int(data[i:i+5], 2) for i in range(0, len(data), 5))
-def to_konami_id(uid):
+ def to_konami_id(uid):
assert len(uid) == 16, "UID must be 16 bytes"
if uid.upper().startswith("E004"):
- card_type = 1
+ card_type = 1
elif uid.upper().startswith("0"):
- card_type = 2
+ card_type = 2
else:
- raise ValueError("Invalid UID prefix")
+ raise ValueError("Invalid UID prefix")
kid = binascii.unhexlify(uid)
assert len(kid) == 8, "ID must be 8 bytes"
@@ -71,20 +71,20 @@ def to_konami_id(uid):
out[0] ^= card_type
out[13] = 1
for i in range(1, 14):
- out[i] ^= out[i - 1]
+ out[i] ^= out[i - 1]
out[14] = card_type
out[15] = checksum(out)
return "".join(ALPHABET[i] for i in out)
-def to_uid(konami_id):
+ def to_uid(konami_id):
if konami_id[14] == "1":
- card_type = 1
+ card_type = 1
elif konami_id[14] == "2":
- card_type = 2
+ card_type = 2
else:
- raise ValueError("Invalid ID")
+ raise ValueError("Invalid ID")
assert len(konami_id) == 16, f"ID must be 16 characters"
assert all(i in ALPHABET for i in konami_id), "ID contains invalid characters"
@@ -94,7 +94,7 @@ def to_uid(konami_id):
assert card[15] == checksum(card), "Checksum failed"
for i in range(13, 0, -1):
- card[i] ^= card[i - 1]
+ card[i] ^= card[i - 1]
card[0] ^= card_type
@@ -102,17 +102,17 @@ def to_uid(konami_id):
card_id = binascii.hexlify(card_id).decode().upper()
if card_type == 1:
- assert card_id[:4] == "E004", "Invalid card type"
+ assert card_id[:4] == "E004", "Invalid card type"
elif card_type == 2:
- assert card_id[0] == "0", "Invalid card type"
+ assert card_id[0] == "0", "Invalid card type"
return card_id
-if __name__ == "__main__":
+ if __name__ == "__main__":
assert to_konami_id("0000000000000000") == "007TUT8XJNSSPN2P", "To KID failed"
assert to_uid("007TUT8XJNSSPN2P") == "0000000000000000", "From KID failed"
assert to_uid(to_konami_id("000000100200F000")) == "000000100200F000", "Roundtrip failed"
-{% endhighlight %}
+ {% endhighlight %}
e-Amusement cards use 16 digit IDs. KONAMI IDs are also 16 digits. Are they related? Yes! In fact, KONAMI IDs are
derived from the ID stored on the e-Amusement card.
@@ -253,13 +253,11 @@ card[15] = checksum(card)
The DES scheme used
For whatever reason, Bemani decided that IDs should be encrypted. Thankfully however they used triple DES, which
almost certainly has an existing implementation in your language of choice. It is triple DES, in CBC mode, with
- a totally null IV
. The key is quite easy to find if you hit the right binaries with
- strings
. Alternatively, check the source of this page. The key
- contains characters that are all within the ASCII range. Before we can use it with DES, the value of every byte
- needs doubled. This was presumably done to give the values more range, but I sincerely doubt it adds any
- additional security.
+ a totally null IV
. The encryption key is ?I'llB2c.YouXXXeMeHaYpy!
. The key consists of
+ characters that are all within the ASCII range. Before we can use it with DES, the value of every byte needs
+ doubled. This was presumably done to give the values more range, but I sincerely doubt it adds any additional
+ security.
-
I'm curious how Bemani implemented this in their own code!
Curiosity is a great thing. Unfortunately, this is code that is implement within the game specific DLL files.
diff --git a/templates/pages/flags.html b/templates/pages/flags.html
deleted file mode 100644
index 02ecaa7..0000000
--- a/templates/pages/flags.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "konami.html" %}
-{% block title %}Curious flags{% endblock %}
-{% block body %}
-
-
-
-{% endblock %}
\ No newline at end of file
diff --git a/templates/pages/sega/software/mxmaster.html b/templates/pages/sega/software/mxmaster.html
index 0085880..eef64e1 100644
--- a/templates/pages/sega/software/mxmaster.html
+++ b/templates/pages/sega/software/mxmaster.html
@@ -17,7 +17,7 @@
s:\mxgdeliver.exe {appboot.platformid} {appboot.gameid} {appboot.networkaddr} {appboot.keyid}
C:\WINDOWS\system32\regini.exe S:\default_regset.txt
c:\System\Execute\mxsegaboot.exe
-
+
{% endblock %}
\ No newline at end of file
diff --git a/templates/pages/transport.html b/templates/pages/transport.html
index e6dc31d..5159478 100644
--- a/templates/pages/transport.html
+++ b/templates/pages/transport.html
@@ -56,8 +56,8 @@ uint32_t prng() {
trying to roll your own!
-Our per-packet key is then generated using md5(seconds | salt | ENC_KEY)
. Identifying
- ENC_KEY
is left as an exercise for the reader, however should not be especially challenging.
+
Our per-packet key is then generated using md5(seconds | salt | ENC_KEY)
. ENC_KEY
is
+ currently 69d74627d985ee2187161570d08d93b12455035b6df0d8205df5
for all games.
Source code details