2. Amusement IC
Many arcade manufacturers allow players to login to games using physical IC cards, such as SEGA’s AiMe, Bandai’s Banapass, or Konami’s e-Amusement Pass; these cards are incompatible with each other.
Amusement IC is a unified standard spear-headed as a joint venture between SEGA and Konami allowing for a single card to be used across all compatible games. Currently the following companies are participating in the standard:
Amusement IC is abbreviated officially as AICC (Amusement IC Card), but as AIC by the community.
Compatible cards must be FeliCa Lite or FeliCa LiteS. Each card is uniquely identified by a 20-digit access code, as with AiMe cards.
Additionally, the IDm field on the card is used to identify the card using network services. All 8 bytes are used for this purpose.
The DFC field is used to identify the specific card vendor. Current vendors are:
DFC | Vendor |
---|---|
00 78 |
SEGA (LiteS) |
00 68 |
Konami (LiteS) |
00 2A |
Bandai Namco Entertainment (LiteS) |
00 3A |
Bandai Namco Games (Lite) |
00 79 |
Nesica |
00 00 |
Reserved for testing |
Bandai Namco Games (FeliCa Edy)
Additionally of note is older Banapass cards, which use FeliCa Edy rather than FeliCa Lite. These cards are not compatible with Amusement IC, however AiMeLib supports them when using a standard card reader, so it is worthwhile being able to identify they. They use the DFC 8C A2
.
2.1 SPAD0
Amusement IC cards are expected to contain their access code, encrypted, in SPAD0. The decrypted structure of this data is shown below. The version uses only the lower nibble, and should be set to 0
.
Note
The version is only accessible after decryption, so I’m not really sure what purpose, if any, it serves! Maybe it describes the algorithm used for computation of the access code? I’ve never seen it meaningfully used.
The encryption is a basic substitution cipher, with a variable number of iterations. There are 9 S-boxes, however the 9th is reserved as a final masking stage, so all S-box indexes are modulo 8.
The 16th byte of the data is used to identify the cipher parameters. The lower nibble is used as the starting S-box index (modulo 8). The upper nibble is used as the number of iterations of the cipher, plus 7. For example, if the final byte was 13
, the initial S-box would be index 3
, and 8
iterations would be performed.
Every iteration of the algorithm:
- Substitute every byte in the first 15 bytes using the current S-box
- Rotate the first 15 bytes left 5 bits
- Increment the current S-box index by 5 (modulo 8)
After all iterations have been performed, a final S-box substitution is performed using the 9th S-box, over all 16 bytes.
To decrypt, perform the steps in reverse.
S-Box Tables
[0]:
afa863a924c0f1bee7b3ac1685b9116f103132aeb17823d2a2caf92b45b83c621a6d828c00d9e27a46192acc13a7e4b7849b8efffb8b03893029d38701bf35da
595ccd097f7041816c5f53c272d4794895b45b39449dfd5171f6d7d52d9fed33eaaa5a176ababde99cce4d7c183b0dee0c80a10a8fb56bf73fd14725c636e87d
7b3ef39975051ce0cf34bb9eeb91ad268dc76608e6584014a6c5fa12ecc4f0218a86d6e106b660742ee3fe272f5ef4b2682856ef9a6122a3c90b02964fdbe590
4a4c92cb9869d057640e3750abbcde7607c83d49fc7794f8c197653a4b836e73881e5d045467df15b0c3932c38ddf5a4550f4e1da01f20a5dc43f2d87e521b42
[1]:
034bb897b78f0d71dc49a790ffa09df8235f206c11f9698eefcbf014df1b7ac6365bc593b62835b23bd1ecf39f80642505cf54af463f9606e510fbaade624151
59e729b54d3df2376ae8168b5ca81e57e209eb32c92eb4f1a476d3c1a5706012b1ea66e14a92a16d3af4d56fdad80a5818632ba35d67776b39c3db4c02bacebb
5501178527e43072c88dfc7819b9432d089b1ad9cd26fa82cc7f75799e65feed91c731d0522a488474dd7de9ae6e3347d6500c53a6bd22ac8a04894240b3455a
44e6a91dc481e3151f5687d43e0f95d7e094ab246807a2987beef5b088c0389c995eadd23c2c21ca8c7e1c61c2347c2f0b839a4fbe4ebc731300f60e86bffdf7
[2]:
4107938a40ff0e2f54fcacd41eb0c889df00644ff3cb2cc08f6e17bf95992a0d51ad4bcaf76955384cc668c3a31f833e0b70c7b24ecffe4dfd8bb496cef9f1d3
4360aed5b3db4ab9e5ea6a485da787dab8062d94c1662426b19a25085c59a6af279288f2ed1b1c11d22216765667149fee5fdc5ba446dd1033297f5ac9978485
42bcab773ca1c2aa374961359c8619575ee6e2a0046dd1a89dec02bdd847621a057d013f186f7544e47af6a9e872f46bfb7eeb3652de79238de77163986cd9e9
3b13900378742081ba3432fa7b31d63d300ae3128e0f1dbba573538280b5d7e13a2bd0e021becd1565b6efcc91f50cc42e9e58f0c59b3909a27c45b7288cf850
[3]:
76cd167fe96b953a4ebb6eccd2b369a972afc782386fbc37a62836bdc3cf85460a996397835688a10264ac795565ffc2ef7a592b1ce08c8f5ae4b49ffcf74547
4aeac00debc878c96703053114ded373fa1fb6501304b77b491af9174d4f8620c1fda0a548e13c60f20b300f4cee8d6dbe8ec6f6d808941b2ab59ea293f522a8
3426a77cec3f0e3bb2f429ce2e428132255f66db7dd7e72d436a5b19ad3e9bc5ab84c46c33dafb8a1154fe574b3d7e09a39140bf68e5b9f396f851ca9ab098ae
1e9c5ee8003912dc0c108b5dd62c27d5618753ba23712f1d74899ddd3515d044b1cbf06258a477e318d4e680d1aa90700124f121d90675b8415c92dfed07e252
[4]:
aa94997492d61c4647792f567af7b50ac906d7fa4011a5ff1fe8008cddb7426e35f0bec21dcab68ee2444e9f51818b4c5d5938d38f25b30931ad0b6b0e50bbd8
9688de49eab44a9a306d2c0fcdf67e4f52d9fb28076319a4ee01f8ebd2f53d0d915b67b857f32be668167b6f65c376e33c2e413ecf54e117a7452d5afcc682ef
cb78ac34ba712722f2123f1a24a8c19ec718e45ffe6cafc837c577bd02297dfd5e83e9bf2a5c73e5dae7ec806a03583b2113d1537093bca110f4648587b061b1
f14362c4f9a2aed40486df26d0ab361e4be06090cc98953a9c9b151b338d4d239d84ceb205a60cb91448d5a375087ced7fdc8966a9c0397220978aa05569db32
[5]:
de5a1b693c42a3514038f117281cb8ace89945a01268ce15c9476dc8464e1ea611f83e31fae62dfd32149c01b1ed5771e330cf0ee7cc374a78ab1d96ea258520
494d7552eeefaf5433f9099e81e1732af23d2213928bf0c0840da804dc8dbb2c9403f5d1d02e5deb5e626f21b091fecb0aecb72f3424d6e96682c6191fd9c1a7
f688028707ddd867c5b929a4c265d353aa3b79e072d7061a58937e0c906e740f4c0be46c43d24136bddb35595fa99f5580398ef3d5e563c377a25b7b7faebaa1
10df4b2b9b16bc00c718fb64fff4f7be0556cd084f6a9a767ab595ca507d7c6ba5c43a8a27dab66123867048979dfc8f5c44b2ad83bf26d4b36098e23f8cb489
[6]:
192e5d7a5b7c7e39ef8b2fcc861bc28c20fb595f21cd9f94a70bba0e477ba506b7d8c926f09d68f25e123a65b05ce222998210f5445074a1f942a8254dea083e
9692c42da22334a9456b797fc84c43672904fab51e05c6b4af1dbbf730edecab40e098e94b11871518beee78b1025790328e61cb3ce6d77531b95436e1dd6c97
62ac41899c60f663bc147d77d50995df174a0c2b5238feb633a451736d4fb3bf71eb693f13001c6f9b35caa32a768d800116033de583708f5a5888f3e30fc307
46ff49fde8ce85d1dcf1b8d36ed4a0ad72dae73b84f8d228dec11a64910ae4c5246ad653c7812cc093d90da6dbaecff455661f37fcbd48aa4e56279ed08ab29a
[7]:
54d94250b874ab32a624486ff07ed730b46d06a288d659394c2caf6ea82b665cb91ce75319568a11d8615f0703dab5b008d0274500c3f5b1796bc45b21e2553d
a0fe319a360feccbbb72291af976876aaec952b7eb7bf305940401c6a1f437e3fbc14fba9e80282f5af6913ecf41adbeb6339bfccec068ee3f51bf4ed249a9f7
8f86c82a6738e44dc72e637fefdf97aa5d620b70d1e6139992f8d3123c6484a70ab29cea1bcc5e431ecd8d93e1713bf2a323e9c2dd988b73965722350ea5ac0c
d49f09db3a1660e589852d771d8120c57aedca1483fa1f2618479d02e05810fd2575bc46dea4154078344a17d50d6965dc4b7c95e88eff7d908c826cb3bd44f1
[8]:
c30bb81500a43dd9fd16e90820e68dc4473825935eaaec2a106e58952653041e929e2f8bbd0a69a93b41f0d0da6aa1711363ef9094b0ebe7dc73b9787ae4c76d
7fa3ac8550f391ea36fa9b8ef7aec1431cc0ca8f4ea23112742c9df1ad3f68bb359a7c03fb092327d44d17de4cee769ca0e175db5b11a721af02424b83d3ce9f
cdcc302b5222cb597d14f9b17054e0815a1d0e4af484ed961ad7c982892d8733e25c513a1bf6e5d8320d5f7288d6b7c6dd1f803764b57bdfffd240fc6005b666
61c82899bca53419f8fe2448d10c55626b86b3ba8a2e6fa6676501e8183e7e77298cf2076ca8794f444606c2ab0fb4b2be98d549e3f5cf975dbf573c39c54556
Inverse S-Box Tables
These can be trivially calculated, but for simplicity:
[0]:
243cba36e385a4d0934373b9706ec9f1100e9b2c97e70b636c2920fe86f3e1f5f69fb616047b8fabb1392a1beb5ca8ac3811125f893e7dcaec53db6d1ed28178
9646fff9541c287a4fd3c0dcc16af2bccb57fd4ae4f0b2c79540625241e2ad49a6b51f02c8da92e5b0c564764821de0f45584cdfa784cfd5154e27806b7ffc44
714722dd300ca13be037a03523903274bf8dc2ead650bbd9c483b43168558b5df47218b7eff7982d010361cc0a8e1300e814af095175a52f1d0d658acd66073d
05d84be99d997c91d1b819c32b426988c679173a4d5ba25afb253fbdf8edcee687a326a92ebe94087e67608c9c5e6fb39e06fa82aeee5977d71a9a34d456aa33
[1]:
f9817c00b93037d590516ef0b206fbcd39145ff81bc74a82708c921deac34ec812e6b610d32f95842542a572e58f55ef86a253aeed262047de786828e445cc35
bc3ebb8ec0be34afa60964017b44f5f3b13fa4b33280c94f6f40bf214c74e1115eeb3d712e9d6275d41648771367ad6b5d0787f7a89a59768b9b1ed8eeaae999
2dc597f1a783fccadcbab84be88917050ba06523d1ce3603d7e0f291df0e9c2c0d66d673585cb40a4dc23bd2b7e2ac33db6027bd56432404028d7d7ff6b5f4fd
dd5bec79c4221fa18854e71998947e31a329e35acb6ab0cf6d936c7a08a93c1cd06350c68538c14149ab61522a9fd9181a57462b69dafaff0f15963a8afe9e0c
[2]:
11a29ac394a051015bf7d130ee1f06d57767d3c16ee76a1aa48e9f6566d60c2dc6e469b7565a5760fc791ee11652f007d0cdca78c98bb38827f6e0c084cf2fa3
04008040a7fa759d4b89462228373413ff20b4da08266c8ff25d7b735c4c9071418a9ebb12e8556d2a254aafbd9519a531baadd9c5a66b83c4b6a9ccf9a1b17a
dcc7db2e7e7f8d4e620f0339fdb8d418c2ec6102531c3b7dbc1d59f58c98f16f9385f82c74d85e4d97ab87820a21425f0d5833443adde9fb5047c8d7819be51b
1754862beff429320e7c2315ebe63c35e296683f0b43cede9cbe4f457276b510e3df92d2a84891b9acbf49b2996470eaf33e6314aeedaa24fe3dcbb009383605
[3]:
c4f02849554af5fd75af2069c843866bc9a8c6544cdd025be89b597734d7c0515ff37ed4f19081ce198a7833cd978cd66a4b8fa480dc1a1714c5078766ad9d85
b2f88d98df3e1f3f645840ac6c5c085d53baffd2a92c25abe432389af9cbc29167d0e322292d9248b40e9905a36f0a15efd5104fd8f600e6462b31578394ae03
eb8e1324a11e5ed126d9a7ca366e7137eeb1fa7c7606b823be21bc9ec1da7a3b62277bb0e56318827f0feda02a9cbf11bde0880d3a795256f7b6d309161b70b3
42602f1ca29f72124547bbe10b018b1ddeec0c4ee9cfcc9574f4a593c7db4dfb3565fee739b5ea96c304414484fc6d30e2f268b7897d733db95a50a63c61aa2e
[4]:
1a599cadc8e41154ed370f3ae65f3c4bb81589b1e8da697791568bdb0624cf18f8b087df8c35cb86539da4664a7a710a4838ffdc8320ce9832f6d7af705e738a
14721ec129790708e94346d02fde2a4f3d2c50b375fc0b64ae317b61a530a093d2bec255ba6cf36268fdac3b95491f6bb485f7a603ec6e9a81090c6aee9e4ef0
ab2d7ea1e1bbc9bc41f2fa2e1bdd2734d36004b501d640f9d50247d9d8e08f2bfbb7c5eb5716e5788df400cd8239c696bdbfe336450e261d63e7843eb69b22a3
f58e236dc3997d9097102580d44ce274ccb25c33c7ea05123f51a8fef11c42cad176286f92a767a919a2445baaef587f21c08865b95d4d0d5ac413527c9f9417
[5]:
c72b82615bd09684d34a70a19b59339fc02014532917c50bc97b97020d3a1e7c3f6b52e8753df6e40c8a4fc35f2665733123284874aaa73609b1e291045122fc
08a605a4f1121c19eb4037c2a0411dd4dc07438f47afd12e98ab01baf06668acf9e769b6cb8d78871503d5dfa31a9d6aea2f944e9e42d7b83892d8bbdedd9abc
b04c79f4583ee98381ffe355fd5db2ef9c6d549960da3becfa11d6c42aed4bae13bfb9068be01f7f5aad90390ff3bd466c2cf2f8fed9e6720e89be5ec6a8cff5
577e8cb7e1887ac81b18db6f35d216326463a58ef7b47695867de5a95c8500c1934dfb30a2b5253410773c67712d4445560a50b3cd6280ce214924caee276ecc
[6]:
a5b06db251551fbf3e8ddd1992ea1bbd326529a48967b1906800da0da65954f210142f45e03b23fad750ac93e643010a5c78709846a97bf395072ad374b33fa3
6082394e3448c01cf6c291644d3cf89d359a94e37af0f96eb912b8042d02281385728087db2bf14f26a2e1497e9ccca7b6a0d09b3677ad8b6b4a031d058a064b
afe531b5d4c60c66ba83fd090fae71b76fdc41e8178e407f6230ffa88425fb16ce3744ab991eeb183a47f75f81cfed582c6cfe9e57539720ca791a5a88f5699f
e7d90ebe42df56e44c22aa730b15c5eefcc7d6cbcd8ce27621e9d1ecc87dd88f617c2ebcdeb475d2c4633da15e5d6a0824c927bbef33865bd5385211f4c396c1
[7]:
345adb2c5957122b30c2a092bfedbc45de279b96d3e6c5ebd8244ba421cca8d6ce3cbab109e0d732664a831d19ca89670f420771e9bb445e8517c4ae9c3f6b78
e76d02a7fe33e3d90a7deaf118877b6203795223003e25b9dd16683b1f90a62ac629918a9def1e8476ee4f39fb111b0b93ad49b705e14dcbe838d055f2f70d8b
65cdfad49ec9814e14c826b6f9aaf580f86a98ab58f3b88eb5974372a2da64c1405c13b0e5bd089f1c7e8f06be6e501a2f37a1fc102e705304206348e2fd6f7a
7561b3353acf5b888251d247a5a9746c31947c9ac0ec150e28012dc3f0b4e48ddcac3d5f86c79522f4b2a35446d1778c0cffaf565d36697f994cd56073df41f6
[8]:
04da79631ebdeae30b652501cda992ed187557308903096adcc798a450911fb10c778566ca121c67c2e01783599dd5228256a89fc66048b311fca328fb06dd5d
ba297a4fe8fee910cbf3937b6c6954e744a2841d8dcefffa1a879074a1f814aabcc0cf31b4d9bfd85e262dd0e43f19d68c2fab3958726edf3be63cb66288de40
b28f9b7c9543d19eac9cd423e10e4b5333462013341b97f7f1c3614a6f5a217f702e554105c5d776e52715ec425c4d78358befd2eeb5beae023ad35fc424f0f9
514eeb000ffdaf3ec19a528681807ef62bccb97d68f2ad99a7072c7338b06bb78e71a0f43da60d37db0a473616966d322a5be24594f5a54cc88a4964bb08c9b8
2.1.1 Code
The following code snippet presents a simple implementation of both encryption and decryption.
S_BOX = [...]
S_BOX_INV = [...]
N_TABLES = len(S_BOX) - 1 # Final table is used for masking
ITER_ADD = 5
def rotate_right(data, n_bytes, n_bits):
prior = data[n_bytes - 1]
for i in range(n_bytes):
prior, data[i] = data[i], (data[i] >> n_bits) | ((prior & ((1 << n_bits) - 1)) << (8 - n_bits))
def rotate_left(data, n_bytes, n_bits):
prior = data[0]
for i in range(n_bytes - 1, -1, -1):
prior, data[i] = data[i], ((data[i] & ((1 << (8 - n_bits)) - 1)) << n_bits) | (prior >> (8 - n_bits))
def encrypt(spad):
spad = bytearray(spad)
count = (spad[15] >> 4) + 7
table = spad[15]
for _ in range(count):
for i in range(15):
spad[i] = S_BOX[table % N_TABLES][spad[i]]
rotate_left(spad, 15, 5)
table += ITER_ADD
return bytearray(S_BOX[N_TABLES][i] for i in spad)
def decrypt(spad):
spad = bytearray(S_BOX_INV[N_TABLES][i] for i in spad)
count = (spad[15] >> 4) + 7
table = spad[15] + ITER_ADD * count
for _ in range(count):
table -= ITER_ADD
rotate_right(spad, 15, 5)
for i in range(15):
spad[i] = S_BOX_INV[table % N_TABLES][spad[i]]
return spad