mirror of
https://gitea.tendokyu.moe/eamuse/docs.git
synced 2024-11-28 00:20:52 +01:00
Yolo encryption keys
This commit is contained in:
parent
a3e32f95a6
commit
1d62abc9f8
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.8 KiB |
@ -10,58 +10,58 @@
|
|||||||
cases too. It's not great code by any stretch, and it liberally uses assertions rather than proper
|
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.</p>
|
exceptions, but it should be a good enough starting point for your own version.</p>
|
||||||
<pre></pre>{% highlight 'python' %}
|
<pre></pre>{% highlight 'python' %}
|
||||||
import binascii
|
import binascii
|
||||||
from Crypto.Cipher import DES3
|
from Crypto.Cipher import DES3
|
||||||
|
|
||||||
|
|
||||||
KEY = b"" # Check the DES section for this
|
KEY = b"?I'llB2c.YouXXXeMeHaYpy!"
|
||||||
_KEY = bytes(i * 2 for i in KEY) # Preprocess the key
|
_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)
|
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
|
||||||
return cipher.encrypt(uid)
|
return cipher.encrypt(uid)
|
||||||
|
|
||||||
|
|
||||||
def dec_des(uid):
|
def dec_des(uid):
|
||||||
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
|
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
|
||||||
return cipher.decrypt(uid)
|
return cipher.decrypt(uid)
|
||||||
|
|
||||||
|
|
||||||
def checksum(data):
|
def checksum(data):
|
||||||
chk = sum(data[i] * (i % 3 + 1) for i in range(15))
|
chk = sum(data[i] * (i % 3 + 1) for i in range(15))
|
||||||
|
|
||||||
while chk > 31:
|
while chk > 31:
|
||||||
chk = (chk >> 5) + (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)
|
data = "".join(f"{i:05b}" for i in data)
|
||||||
if len(data) % 8 != 0:
|
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))
|
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)
|
data = "".join(f"{i:08b}" for i in data)
|
||||||
if len(data) % 5 != 0:
|
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))
|
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"
|
assert len(uid) == 16, "UID must be 16 bytes"
|
||||||
|
|
||||||
if uid.upper().startswith("E004"):
|
if uid.upper().startswith("E004"):
|
||||||
card_type = 1
|
card_type = 1
|
||||||
elif uid.upper().startswith("0"):
|
elif uid.upper().startswith("0"):
|
||||||
card_type = 2
|
card_type = 2
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid UID prefix")
|
raise ValueError("Invalid UID prefix")
|
||||||
|
|
||||||
kid = binascii.unhexlify(uid)
|
kid = binascii.unhexlify(uid)
|
||||||
assert len(kid) == 8, "ID must be 8 bytes"
|
assert len(kid) == 8, "ID must be 8 bytes"
|
||||||
@ -71,20 +71,20 @@ def to_konami_id(uid):
|
|||||||
out[0] ^= card_type
|
out[0] ^= card_type
|
||||||
out[13] = 1
|
out[13] = 1
|
||||||
for i in range(1, 14):
|
for i in range(1, 14):
|
||||||
out[i] ^= out[i - 1]
|
out[i] ^= out[i - 1]
|
||||||
out[14] = card_type
|
out[14] = card_type
|
||||||
out[15] = checksum(out)
|
out[15] = checksum(out)
|
||||||
|
|
||||||
return "".join(ALPHABET[i] for i in out)
|
return "".join(ALPHABET[i] for i in out)
|
||||||
|
|
||||||
|
|
||||||
def to_uid(konami_id):
|
def to_uid(konami_id):
|
||||||
if konami_id[14] == "1":
|
if konami_id[14] == "1":
|
||||||
card_type = 1
|
card_type = 1
|
||||||
elif konami_id[14] == "2":
|
elif konami_id[14] == "2":
|
||||||
card_type = 2
|
card_type = 2
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid ID")
|
raise ValueError("Invalid ID")
|
||||||
|
|
||||||
assert len(konami_id) == 16, f"ID must be 16 characters"
|
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"
|
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"
|
assert card[15] == checksum(card), "Checksum failed"
|
||||||
|
|
||||||
for i in range(13, 0, -1):
|
for i in range(13, 0, -1):
|
||||||
card[i] ^= card[i - 1]
|
card[i] ^= card[i - 1]
|
||||||
|
|
||||||
card[0] ^= card_type
|
card[0] ^= card_type
|
||||||
|
|
||||||
@ -102,17 +102,17 @@ def to_uid(konami_id):
|
|||||||
card_id = binascii.hexlify(card_id).decode().upper()
|
card_id = binascii.hexlify(card_id).decode().upper()
|
||||||
|
|
||||||
if card_type == 1:
|
if card_type == 1:
|
||||||
assert card_id[:4] == "E004", "Invalid card type"
|
assert card_id[:4] == "E004", "Invalid card type"
|
||||||
elif card_type == 2:
|
elif card_type == 2:
|
||||||
assert card_id[0] == "0", "Invalid card type"
|
assert card_id[0] == "0", "Invalid card type"
|
||||||
return card_id
|
return card_id
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
assert to_konami_id("0000000000000000") == "007TUT8XJNSSPN2P", "To KID failed"
|
assert to_konami_id("0000000000000000") == "007TUT8XJNSSPN2P", "To KID failed"
|
||||||
assert to_uid("007TUT8XJNSSPN2P") == "0000000000000000", "From KID failed"
|
assert to_uid("007TUT8XJNSSPN2P") == "0000000000000000", "From KID failed"
|
||||||
assert to_uid(to_konami_id("000000100200F000")) == "000000100200F000", "Roundtrip failed"
|
assert to_uid(to_konami_id("000000100200F000")) == "000000100200F000", "Roundtrip failed"
|
||||||
{% endhighlight %}</pre>
|
{% endhighlight %}</pre>
|
||||||
</details>
|
</details>
|
||||||
<p>e-Amusement cards use 16 digit IDs. KONAMI IDs are also 16 digits. Are they related? Yes! In fact, KONAMI IDs are
|
<p>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.</p>
|
derived from the ID stored on the e-Amusement card.</p>
|
||||||
@ -253,13 +253,11 @@ card[15] = <a href="#checksum">checksum(card)</a></code></pre>
|
|||||||
<h2 id="des">The DES scheme used</h2>
|
<h2 id="des">The DES scheme used</h2>
|
||||||
<p>For whatever reason, Bemani decided that IDs should be encrypted. Thankfully however they used triple DES, which
|
<p>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
|
almost certainly has an existing implementation in your language of choice. It is triple DES, in CBC mode, with
|
||||||
a totally null <code>IV</code>. The key is quite easy to find if you hit the right binaries with
|
a totally null <code>IV</code>. The encryption key is <code>?I'llB2c.YouXXXeMeHaYpy!</code>. The key consists of
|
||||||
<code>strings</code>. <span style="color: white">Alternatively, check the source of this page.</span> The key
|
characters that are all within the ASCII range. Before we can use it with DES, the value of every byte needs
|
||||||
contains characters that are all within the ASCII range. Before we can use it with DES, the value of every byte
|
doubled. This was presumably done to give the values more range, but I sincerely doubt it adds any additional
|
||||||
needs doubled. This was presumably done to give the values more range, but I sincerely doubt it adds any
|
security.
|
||||||
additional security.
|
|
||||||
</p>
|
</p>
|
||||||
<!-- soundvoltex.dll:0x102d3e2d -->
|
|
||||||
<details>
|
<details>
|
||||||
<summary>I'm curious how Bemani implemented this in their own code!</summary>
|
<summary>I'm curious how Bemani implemented this in their own code!</summary>
|
||||||
<p>Curiosity is a great thing. Unfortunately, this is code that is implement within the game specific DLL files.
|
<p>Curiosity is a great thing. Unfortunately, this is code that is implement within the game specific DLL files.
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
{% extends "konami.html" %}
|
|
||||||
{% block title %}Curious flags{% endblock %}
|
|
||||||
{% block body %}
|
|
||||||
<br>
|
|
||||||
<img src="{{ROOT}}/images/flags/xeai.png" class="graphic">
|
|
||||||
<img src="{{ROOT}}/images/flags/card.png" class="graphic">
|
|
||||||
{% endblock %}
|
|
@ -17,7 +17,7 @@
|
|||||||
<li><code>s:\mxgdeliver.exe {appboot.platformid} {appboot.gameid} {appboot.networkaddr} {appboot.keyid}</code></li>
|
<li><code>s:\mxgdeliver.exe {appboot.platformid} {appboot.gameid} {appboot.networkaddr} {appboot.keyid}</code></li>
|
||||||
<li><code>C:\WINDOWS\system32\regini.exe S:\default_regset.txt</code></li>
|
<li><code>C:\WINDOWS\system32\regini.exe S:\default_regset.txt</code></li>
|
||||||
<li><code>c:\System\Execute\mxsegaboot.exe</code></li>
|
<li><code>c:\System\Execute\mxsegaboot.exe</code></li>
|
||||||
<!-- Investigate amDongleSetAuthConfig->FUN_00412ae0 -->
|
<!-- TODO: Investigate amDongleSetAuthConfig->FUN_00412ae0 -->
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -56,8 +56,8 @@ uint32_t prng() {
|
|||||||
trying to roll your own!
|
trying to roll your own!
|
||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<p>Our per-packet key is then generated using <code>md5(seconds | salt | ENC_KEY)</code>. Identifying
|
<p>Our per-packet key is then generated using <code>md5(seconds | salt | ENC_KEY)</code>. <code>ENC_KEY</code> is
|
||||||
<code>ENC_KEY</code> is left as an exercise for the reader, however should not be especially challenging.
|
currently <code>69d74627d985ee2187161570d08d93b12455035b6df0d8205df5</code> for all games.
|
||||||
</p>
|
</p>
|
||||||
<details>
|
<details>
|
||||||
<summary>Source code details</summary>
|
<summary>Source code details</summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user