mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-26 13:21:01 -04:00
Deprecate some methods in favor of using properties directly, this is cleaner
This commit is contained in:
parent
817fe1b499
commit
3fd5bfd5df
@ -14,7 +14,7 @@ from .crypto import decrypt_content
|
|||||||
class ContentRegion:
|
class ContentRegion:
|
||||||
"""Creates a ContentRegion object to parse the continuous content region of a WAD.
|
"""Creates a ContentRegion object to parse the continuous content region of a WAD.
|
||||||
|
|
||||||
Attributes:
|
Parameters
|
||||||
----------
|
----------
|
||||||
content_region : bytes
|
content_region : bytes
|
||||||
A bytes object containing the content region of a WAD file.
|
A bytes object containing the content region of a WAD file.
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
import struct
|
import struct
|
||||||
from .commonkeys import get_common_key
|
from .commonkeys import get_common_key
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
from Crypto.Util.Padding import pad, unpad
|
|
||||||
|
|
||||||
|
|
||||||
def decrypt_title_key(title_key_enc, common_key_index, title_id) -> bytes:
|
def decrypt_title_key(title_key_enc, common_key_index, title_id) -> bytes:
|
||||||
|
@ -13,7 +13,7 @@ from typing import List
|
|||||||
class TitleLimit:
|
class TitleLimit:
|
||||||
"""Creates a TitleLimit object that contains the type of restriction and the limit.
|
"""Creates a TitleLimit object that contains the type of restriction and the limit.
|
||||||
|
|
||||||
Attributes:
|
Attributes
|
||||||
----------
|
----------
|
||||||
limit_type : int
|
limit_type : int
|
||||||
The type of play limit applied.
|
The type of play limit applied.
|
||||||
@ -31,12 +31,28 @@ class TitleLimit:
|
|||||||
class Ticket:
|
class Ticket:
|
||||||
"""Creates a Ticket object to parse a Ticket file to retrieve the Title Key needed to decrypt it.
|
"""Creates a Ticket object to parse a Ticket file to retrieve the Title Key needed to decrypt it.
|
||||||
|
|
||||||
Attributes:
|
Parameters
|
||||||
----------
|
----------
|
||||||
ticket : bytes
|
ticket : bytes
|
||||||
A bytes object containing the contents of a ticket file.
|
A bytes object containing the contents of a ticket file.
|
||||||
"""
|
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
signature : bytes
|
||||||
|
The signature applied to the ticket.
|
||||||
|
ticket_version : int
|
||||||
|
The version of the ticket.
|
||||||
|
title_key_enc : bytes
|
||||||
|
The Title Key contained in the ticket, in encrypted form.
|
||||||
|
ticket_id : bytes
|
||||||
|
The unique ID of this ticket, used for console-specific title installations.
|
||||||
|
console_id : int
|
||||||
|
The unique ID of the console this ticket was designed for, if this is a console-specific ticket.
|
||||||
|
title_version : int
|
||||||
|
The version of the title this ticket was designed for.
|
||||||
|
common_key_index : int
|
||||||
|
The index of the common key required to decrypt this ticket's Title Key.
|
||||||
|
"""
|
||||||
def __init__(self, ticket):
|
def __init__(self, ticket):
|
||||||
self.ticket = ticket
|
self.ticket = ticket
|
||||||
# Signature blob header
|
# Signature blob header
|
||||||
@ -45,7 +61,7 @@ class Ticket:
|
|||||||
# v0 ticket data
|
# v0 ticket data
|
||||||
self.signature_issuer: str # Who issued the signature for the ticket
|
self.signature_issuer: str # Who issued the signature for the ticket
|
||||||
self.ecdh_data: bytes # Involved in created one-time keys for console-specific title installs.
|
self.ecdh_data: bytes # Involved in created one-time keys for console-specific title installs.
|
||||||
self.ticket_version: int # The version of the ticket format.
|
self.ticket_version: int # The version of the current ticket file.
|
||||||
self.title_key_enc: bytes # The title key of the ticket's respective title, encrypted by a common key.
|
self.title_key_enc: bytes # The title key of the ticket's respective title, encrypted by a common key.
|
||||||
self.ticket_id: bytes # Used as the IV when decrypting the title key for console-specific title installs.
|
self.ticket_id: bytes # Used as the IV when decrypting the title key for console-specific title installs.
|
||||||
self.console_id: int # ID of the console that the ticket was issued for.
|
self.console_id: int # ID of the console that the ticket was issued for.
|
||||||
@ -118,56 +134,6 @@ class Ticket:
|
|||||||
limit_value = int.from_bytes(ticket_data.read(4))
|
limit_value = int.from_bytes(ticket_data.read(4))
|
||||||
self.title_limits_list.append(TitleLimit(limit_type, limit_value))
|
self.title_limits_list.append(TitleLimit(limit_type, limit_value))
|
||||||
|
|
||||||
def get_signature(self):
|
|
||||||
"""Gets the signature of the ticket.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
bytes
|
|
||||||
The signature.
|
|
||||||
"""
|
|
||||||
return self.signature
|
|
||||||
|
|
||||||
def get_ticket_version(self):
|
|
||||||
"""Gets the version of the ticket.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The version.
|
|
||||||
"""
|
|
||||||
return self.ticket_version
|
|
||||||
|
|
||||||
def get_title_key_enc(self):
|
|
||||||
"""Gets the Title Key contained in the ticket, in encrypted form.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
bytes
|
|
||||||
The encrypted Title Key.
|
|
||||||
"""
|
|
||||||
return self.title_key_enc
|
|
||||||
|
|
||||||
def get_ticket_id(self):
|
|
||||||
"""Gets the ID of the ticket.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
bytes
|
|
||||||
The ID of the ticket.
|
|
||||||
"""
|
|
||||||
return self.ticket_id
|
|
||||||
|
|
||||||
def get_console_id(self):
|
|
||||||
"""Gets the ID of the console this ticket is designed for, if the ticket is console-specific.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
bytes
|
|
||||||
The ID of the console.
|
|
||||||
"""
|
|
||||||
return self.console_id
|
|
||||||
|
|
||||||
def get_title_id(self):
|
def get_title_id(self):
|
||||||
"""Gets the Title ID of the ticket's associated title.
|
"""Gets the Title ID of the ticket's associated title.
|
||||||
|
|
||||||
@ -179,30 +145,6 @@ class Ticket:
|
|||||||
title_id_str = str(self.title_id.decode())
|
title_id_str = str(self.title_id.decode())
|
||||||
return title_id_str
|
return title_id_str
|
||||||
|
|
||||||
def get_title_version(self):
|
|
||||||
"""Gets the version of the ticket's associated title that this ticket is designed for.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The version of the title.
|
|
||||||
"""
|
|
||||||
return self.title_version
|
|
||||||
|
|
||||||
def get_common_key_index(self):
|
|
||||||
"""Gets the index of the common key used to encrypt the Title Key contained in the ticket.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The index of the common key required.
|
|
||||||
|
|
||||||
See Also
|
|
||||||
--------
|
|
||||||
commonkeys.get_common_key
|
|
||||||
"""
|
|
||||||
return self.common_key_index
|
|
||||||
|
|
||||||
def get_common_key_type(self):
|
def get_common_key_type(self):
|
||||||
"""Gets the name of the common key used to encrypt the Title Key contained in the ticket.
|
"""Gets the name of the common key used to encrypt the Title Key contained in the ticket.
|
||||||
|
|
||||||
@ -233,4 +175,3 @@ class Ticket:
|
|||||||
"""
|
"""
|
||||||
title_key = decrypt_title_key(self.title_key_enc, self.common_key_index, self.title_id)
|
title_key = decrypt_title_key(self.title_key_enc, self.common_key_index, self.title_id)
|
||||||
return title_key
|
return title_key
|
||||||
|
|
||||||
|
@ -14,17 +14,32 @@ class TMD:
|
|||||||
"""
|
"""
|
||||||
Creates a TMD object to parse a TMD file to retrieve information about a title.
|
Creates a TMD object to parse a TMD file to retrieve information about a title.
|
||||||
|
|
||||||
Attributes:
|
Parameters
|
||||||
----------
|
----------
|
||||||
tmd : bytes
|
tmd : bytes
|
||||||
A bytes object containing the contents of a TMD file.
|
A bytes object containing the contents of a TMD file.
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
title_id : str
|
||||||
|
The title ID of the title listed in the TMD.
|
||||||
|
title_version : int
|
||||||
|
The version of the title listed in the TMD.
|
||||||
|
tmd_version : int
|
||||||
|
The version of the TMD.
|
||||||
|
ios_tid : str
|
||||||
|
The title ID of the IOS the title runs on.
|
||||||
|
ios_version : int
|
||||||
|
The IOS version the title runs on.
|
||||||
|
num_contents : int
|
||||||
|
The number of contents listed in the TMD.
|
||||||
"""
|
"""
|
||||||
def __init__(self, tmd):
|
def __init__(self, tmd):
|
||||||
self.tmd = tmd
|
self.tmd = tmd
|
||||||
self.sig_type: int
|
self.sig_type: int
|
||||||
self.sig: bytearray
|
self.sig: bytearray
|
||||||
self.issuer: bytearray # Follows the format "Root-CA%08x-CP%08x"
|
self.issuer: bytearray # Follows the format "Root-CA%08x-CP%08x"
|
||||||
self.version: int # This seems to always be 0 no matter what?
|
self.tmd_version: int # This seems to always be 0 no matter what?
|
||||||
self.ca_crl_version: int
|
self.ca_crl_version: int
|
||||||
self.signer_crl_version: int
|
self.signer_crl_version: int
|
||||||
self.vwii: int # Whether the title is for the vWii. 0 = No, 1 = Yes
|
self.vwii: int # Whether the title is for the vWii. 0 = No, 1 = Yes
|
||||||
@ -50,7 +65,7 @@ class TMD:
|
|||||||
self.issuer = tmd_data.read(64)
|
self.issuer = tmd_data.read(64)
|
||||||
# TMD version, seems to usually be 0, but I've seen references to other numbers
|
# TMD version, seems to usually be 0, but I've seen references to other numbers
|
||||||
tmd_data.seek(0x180)
|
tmd_data.seek(0x180)
|
||||||
self.version = int.from_bytes(tmd_data.read(1))
|
self.tmd_version = int.from_bytes(tmd_data.read(1))
|
||||||
# TODO: label
|
# TODO: label
|
||||||
tmd_data.seek(0x181)
|
tmd_data.seek(0x181)
|
||||||
self.ca_crl_version = tmd_data.read(1)
|
self.ca_crl_version = tmd_data.read(1)
|
||||||
@ -111,26 +126,6 @@ class TMD:
|
|||||||
int(content_record_hdr[2]), int.from_bytes(content_record_hdr[3]),
|
int(content_record_hdr[2]), int.from_bytes(content_record_hdr[3]),
|
||||||
binascii.hexlify(content_record_hdr[4])))
|
binascii.hexlify(content_record_hdr[4])))
|
||||||
|
|
||||||
def get_title_id(self):
|
|
||||||
"""Gets the TID of the TMD's associated title.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
str
|
|
||||||
The Title ID.
|
|
||||||
"""
|
|
||||||
return self.title_id
|
|
||||||
|
|
||||||
def get_title_version(self):
|
|
||||||
"""Gets the version of the TMD's associated title.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The version of the title.
|
|
||||||
"""
|
|
||||||
return self.title_version
|
|
||||||
|
|
||||||
def get_title_region(self):
|
def get_title_region(self):
|
||||||
"""Gets the region of the TMD's associated title.
|
"""Gets the region of the TMD's associated title.
|
||||||
|
|
||||||
@ -167,36 +162,6 @@ class TMD:
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_tmd_version(self):
|
|
||||||
"""Gets the version of the TMD.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The version of the TMD.
|
|
||||||
"""
|
|
||||||
return self.version
|
|
||||||
|
|
||||||
def get_required_ios_tid(self):
|
|
||||||
"""Gets the TID of the required IOS for the title.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
str
|
|
||||||
The Title ID of the required IOS version.
|
|
||||||
"""
|
|
||||||
return self.ios_tid
|
|
||||||
|
|
||||||
def get_required_ios(self):
|
|
||||||
"""Gets the required IOS version for the title.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The required IOS version.
|
|
||||||
"""
|
|
||||||
return self.ios_version
|
|
||||||
|
|
||||||
def get_title_type(self):
|
def get_title_type(self):
|
||||||
"""Gets the type of the TMD's associated title.
|
"""Gets the type of the TMD's associated title.
|
||||||
|
|
||||||
@ -252,16 +217,6 @@ class TMD:
|
|||||||
case _:
|
case _:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
|
|
||||||
def get_num_contents(self):
|
|
||||||
"""Gets the number of contents listed in the TMD.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The number of contents.
|
|
||||||
"""
|
|
||||||
return self.num_contents
|
|
||||||
|
|
||||||
def get_content_record(self, record):
|
def get_content_record(self, record):
|
||||||
"""Gets the content record at the specified index.
|
"""Gets the content record at the specified index.
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ class ContentRecord:
|
|||||||
"""
|
"""
|
||||||
Creates a content record object that contains the details of a content contained in a title.
|
Creates a content record object that contains the details of a content contained in a title.
|
||||||
|
|
||||||
Attributes:
|
Attributes
|
||||||
----------
|
----------
|
||||||
content_id : int
|
content_id : int
|
||||||
ID of the content.
|
ID of the content.
|
||||||
|
@ -11,7 +11,7 @@ class WAD:
|
|||||||
"""
|
"""
|
||||||
Creates a WAD object to parse the header of a WAD file and retrieve the data contained in it.
|
Creates a WAD object to parse the header of a WAD file and retrieve the data contained in it.
|
||||||
|
|
||||||
Attributes:
|
Parameters
|
||||||
----------
|
----------
|
||||||
wad : bytes
|
wad : bytes
|
||||||
A bytes object containing the contents of a WAD file.
|
A bytes object containing the contents of a WAD file.
|
||||||
@ -76,7 +76,7 @@ class WAD:
|
|||||||
self.wad_tik_offset = int(64 * round((self.wad_crl_offset + self.wad_crl_size) / 64))
|
self.wad_tik_offset = int(64 * round((self.wad_crl_offset + self.wad_crl_size) / 64))
|
||||||
self.wad_tmd_offset = int(64 * round((self.wad_tik_offset + self.wad_tik_size) / 64))
|
self.wad_tmd_offset = int(64 * round((self.wad_tik_offset + self.wad_tik_size) / 64))
|
||||||
self.wad_content_offset = int(64 * round((self.wad_tmd_offset + self.wad_tmd_size) / 64))
|
self.wad_content_offset = int(64 * round((self.wad_tmd_offset + self.wad_tmd_size) / 64))
|
||||||
# meta is also never used, but Nintendo's tools calculate it so we should too.
|
# meta is also never used, but Nintendo's tools calculate it, so we should too.
|
||||||
self.wad_meta_offset = int(64 * round((self.wad_content_offset + self.wad_content_size) / 64))
|
self.wad_meta_offset = int(64 * round((self.wad_content_offset + self.wad_content_size) / 64))
|
||||||
|
|
||||||
def get_cert_region(self):
|
def get_cert_region(self):
|
||||||
@ -137,7 +137,19 @@ class WAD:
|
|||||||
int
|
int
|
||||||
The size of the content data in the WAD.
|
The size of the content data in the WAD.
|
||||||
"""
|
"""
|
||||||
return self.wad_content_offset, self.wad_tmd_size
|
return self.wad_content_offset, self.wad_content_size
|
||||||
|
|
||||||
|
def get_meta_region(self):
|
||||||
|
"""Gets the offset and size of the meta region of the WAD, which is typically unused.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
int
|
||||||
|
The offset of the meta region in the WAD.
|
||||||
|
int
|
||||||
|
The size of the meta region in the WAD.
|
||||||
|
"""
|
||||||
|
return self.wad_meta_offset, self.wad_meta_size
|
||||||
|
|
||||||
def get_wad_type(self):
|
def get_wad_type(self):
|
||||||
"""Gets the type of the WAD.
|
"""Gets the type of the WAD.
|
||||||
@ -157,9 +169,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The certificate data.
|
The certificate data.
|
||||||
"""
|
"""
|
||||||
waddata = io.BytesIO(self.wad)
|
wad_data = io.BytesIO(self.wad)
|
||||||
waddata.seek(self.wad_cert_offset)
|
wad_data.seek(self.wad_cert_offset)
|
||||||
cert_data = waddata.read(self.wad_cert_size)
|
cert_data = wad_data.read(self.wad_cert_size)
|
||||||
return cert_data
|
return cert_data
|
||||||
|
|
||||||
def get_crl_data(self):
|
def get_crl_data(self):
|
||||||
@ -170,9 +182,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The crl data.
|
The crl data.
|
||||||
"""
|
"""
|
||||||
waddata = io.BytesIO(self.wad)
|
wad_data = io.BytesIO(self.wad)
|
||||||
waddata.seek(self.wad_crl_offset)
|
wad_data.seek(self.wad_crl_offset)
|
||||||
crl_data = waddata.read(self.wad_crl_size)
|
crl_data = wad_data.read(self.wad_crl_size)
|
||||||
return crl_data
|
return crl_data
|
||||||
|
|
||||||
def get_ticket_data(self):
|
def get_ticket_data(self):
|
||||||
@ -183,9 +195,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The ticket data.
|
The ticket data.
|
||||||
"""
|
"""
|
||||||
waddata = io.BytesIO(self.wad)
|
wad_data = io.BytesIO(self.wad)
|
||||||
waddata.seek(self.wad_tik_offset)
|
wad_data.seek(self.wad_tik_offset)
|
||||||
ticket_data = waddata.read(self.wad_tik_size)
|
ticket_data = wad_data.read(self.wad_tik_size)
|
||||||
return ticket_data
|
return ticket_data
|
||||||
|
|
||||||
def get_tmd_data(self):
|
def get_tmd_data(self):
|
||||||
@ -196,9 +208,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The TMD data.
|
The TMD data.
|
||||||
"""
|
"""
|
||||||
waddata = io.BytesIO(self.wad)
|
wad_data = io.BytesIO(self.wad)
|
||||||
waddata.seek(self.wad_tmd_offset)
|
wad_data.seek(self.wad_tmd_offset)
|
||||||
tmd_data = waddata.read(self.wad_tmd_size)
|
tmd_data = wad_data.read(self.wad_tmd_size)
|
||||||
return tmd_data
|
return tmd_data
|
||||||
|
|
||||||
def get_content_data(self):
|
def get_content_data(self):
|
||||||
@ -209,7 +221,20 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The content data.
|
The content data.
|
||||||
"""
|
"""
|
||||||
waddata = io.BytesIO(self.wad)
|
wad_data = io.BytesIO(self.wad)
|
||||||
waddata.seek(self.wad_content_offset)
|
wad_data.seek(self.wad_content_offset)
|
||||||
content_data = waddata.read(self.wad_content_size)
|
content_data = wad_data.read(self.wad_content_size)
|
||||||
return content_data
|
return content_data
|
||||||
|
|
||||||
|
def get_meta_data(self):
|
||||||
|
"""Gets the meta region of the WAD, which is typically unused.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bytes
|
||||||
|
The meta region.
|
||||||
|
"""
|
||||||
|
wad_data = io.BytesIO(self.wad)
|
||||||
|
wad_data.seek(self.wad_meta_offset)
|
||||||
|
meta_data = wad_data.read(self.wad_meta_size)
|
||||||
|
return meta_data
|
||||||
|
Loading…
x
Reference in New Issue
Block a user