diff --git a/images/flags/card.png b/images/flags/card.png deleted file mode 100644 index 1ea9156..0000000 Binary files a/images/flags/card.png and /dev/null differ diff --git a/images/flags/xeai.png b/images/flags/xeai.png deleted file mode 100644 index 1c63e60..0000000 Binary files a/images/flags/xeai.png and /dev/null differ 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