mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-26 13:21:01 -04:00
Replaced unnecessary BytesIO usages with standard variables
This commit is contained in:
parent
98666285db
commit
045613216a
@ -79,21 +79,18 @@ class ContentRegion:
|
||||
bytes
|
||||
The full WAD file as bytes.
|
||||
"""
|
||||
# Open the stream and begin writing data to it.
|
||||
with io.BytesIO() as content_region_data:
|
||||
content_region_data = b''
|
||||
for content in self.content_list:
|
||||
# Calculate padding after this content before the next one.
|
||||
padding_bytes = 0
|
||||
if (len(content) % 64) != 0:
|
||||
padding_bytes = 64 - (len(content) % 64)
|
||||
# Write content data, then the padding afterward if necessary.
|
||||
content_region_data.write(content)
|
||||
content_region_data += content
|
||||
if padding_bytes > 0:
|
||||
content_region_data.write(b'\x00' * padding_bytes)
|
||||
content_region_data.seek(0x0)
|
||||
content_region_raw = content_region_data.read()
|
||||
content_region_data += b'\x00' * padding_bytes
|
||||
# Return the raw ContentRegion for the data contained in the object.
|
||||
return content_region_raw
|
||||
return content_region_data
|
||||
|
||||
def get_enc_content_by_index(self, index: int) -> bytes:
|
||||
"""
|
||||
|
@ -1,5 +1,6 @@
|
||||
# "crypto.py" from libWiiPy by NinjaCheetah & Contributors
|
||||
# https://github.com/NinjaCheetah/libWiiPy
|
||||
|
||||
import struct
|
||||
from .commonkeys import get_common_key
|
||||
from .shared import convert_tid_to_iv
|
||||
|
@ -3,7 +3,6 @@
|
||||
#
|
||||
# See https://wiibrew.org/wiki/NUS for details about the NUS
|
||||
|
||||
import io
|
||||
import requests
|
||||
import hashlib
|
||||
from typing import List
|
||||
@ -151,15 +150,13 @@ def download_cert(wiiu_endpoint: bool = False) -> bytes:
|
||||
tmd = requests.get(url=tmd_url, headers={'User-Agent': 'wii libnup/1.0'}, stream=True).content
|
||||
cetk = requests.get(url=cetk_url, headers={'User-Agent': 'wii libnup/1.0'}, stream=True).content
|
||||
# Assemble the certificate.
|
||||
with io.BytesIO() as cert_data:
|
||||
cert = b''
|
||||
# Certificate Authority data.
|
||||
cert_data.write(cetk[0x2A4 + 768:])
|
||||
cert += cetk[0x2A4 + 768:]
|
||||
# Certificate Policy data.
|
||||
cert_data.write(tmd[0x328:0x328 + 768])
|
||||
cert += tmd[0x328:0x328 + 768]
|
||||
# XS data.
|
||||
cert_data.write(cetk[0x2A4:0x2A4 + 768])
|
||||
cert_data.seek(0x0)
|
||||
cert = cert_data.read()
|
||||
cert += cetk[0x2A4:0x2A4 + 768]
|
||||
# Since the cert is always the same, check the hash to make sure nothing went wildly wrong.
|
||||
if hashlib.sha1(cert).hexdigest() != "ace0f15d2a851c383fe4657afc3840d6ffe30ad0":
|
||||
raise Exception("An unknown error has occurred downloading and creating the certificate.")
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
import binascii
|
||||
|
||||
|
||||
def align_value(value, alignment=64) -> int:
|
||||
"""
|
||||
Aligns the provided value to the set alignment (defaults to 64).
|
||||
@ -28,24 +29,24 @@ def align_value(value, alignment=64) -> int:
|
||||
return value
|
||||
|
||||
|
||||
def pad_bytes_stream(data, alignment=64) -> bytes:
|
||||
def pad_bytes(data, alignment=64) -> bytes:
|
||||
"""
|
||||
Pads the provided bytes stream to the provided alignment (defaults to 64).
|
||||
Pads the provided bytes object to the provided alignment (defaults to 64).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
data : BytesIO
|
||||
data : bytes
|
||||
The data to align.
|
||||
alignment : int
|
||||
The number to align to. Defaults to 64.
|
||||
|
||||
Returns
|
||||
-------
|
||||
BytesIO
|
||||
bytes
|
||||
The aligned data.
|
||||
"""
|
||||
while (data.getbuffer().nbytes % alignment) != 0:
|
||||
data.write(b'\x00')
|
||||
while (len(data) % alignment) != 0:
|
||||
data += b'\x00'
|
||||
return data
|
||||
|
||||
|
||||
|
@ -146,68 +146,62 @@ class Ticket:
|
||||
bytes
|
||||
The full Ticket file as bytes.
|
||||
"""
|
||||
# Open the stream and begin writing to it.
|
||||
with io.BytesIO() as ticket_data:
|
||||
ticket_data = b''
|
||||
# Signature type.
|
||||
ticket_data.write(self.signature_type)
|
||||
ticket_data += self.signature_type
|
||||
# Signature data.
|
||||
ticket_data.write(self.signature)
|
||||
ticket_data += self.signature
|
||||
# Padding to 64 bytes.
|
||||
ticket_data.write(b'\x00' * 60)
|
||||
ticket_data += b'\x00' * 60
|
||||
# Signature issuer.
|
||||
ticket_data.write(str.encode(self.signature_issuer))
|
||||
ticket_data += str.encode(self.signature_issuer)
|
||||
# ECDH data.
|
||||
ticket_data.write(self.ecdh_data)
|
||||
ticket_data += self.ecdh_data
|
||||
# Ticket version.
|
||||
ticket_data.write(int.to_bytes(self.ticket_version, 1))
|
||||
ticket_data += int.to_bytes(self.ticket_version, 1)
|
||||
# Reserved (all \0x00).
|
||||
ticket_data.write(b'\x00\x00')
|
||||
ticket_data += b'\x00\x00'
|
||||
# Title Key.
|
||||
ticket_data.write(self.title_key_enc)
|
||||
ticket_data += self.title_key_enc
|
||||
# Unknown (write \0x00).
|
||||
ticket_data.write(b'\x00')
|
||||
ticket_data += b'\x00'
|
||||
# Ticket ID.
|
||||
ticket_data.write(self.ticket_id)
|
||||
ticket_data += self.ticket_id
|
||||
# Console ID.
|
||||
ticket_data.write(int.to_bytes(self.console_id, 4))
|
||||
ticket_data += int.to_bytes(self.console_id, 4)
|
||||
# Title ID.
|
||||
ticket_data.write(binascii.unhexlify(self.title_id))
|
||||
ticket_data += binascii.unhexlify(self.title_id)
|
||||
# Unknown data 1.
|
||||
ticket_data.write(self.unknown1)
|
||||
ticket_data += self.unknown1
|
||||
# Title version.
|
||||
title_version_high = round(self.title_version / 256)
|
||||
ticket_data.write(int.to_bytes(title_version_high, 1))
|
||||
ticket_data += int.to_bytes(title_version_high, 1)
|
||||
title_version_low = self.title_version % 256
|
||||
ticket_data.write(int.to_bytes(title_version_low, 1))
|
||||
ticket_data += int.to_bytes(title_version_low, 1)
|
||||
# Permitted titles mask.
|
||||
ticket_data.write(self.permitted_titles)
|
||||
ticket_data += self.permitted_titles
|
||||
# Permit mask.
|
||||
ticket_data.write(self.permit_mask)
|
||||
ticket_data += self.permit_mask
|
||||
# Title Export allowed.
|
||||
ticket_data.write(int.to_bytes(self.title_export_allowed, 1))
|
||||
ticket_data += int.to_bytes(self.title_export_allowed, 1)
|
||||
# Common Key index.
|
||||
ticket_data.write(int.to_bytes(self.common_key_index, 1))
|
||||
ticket_data += int.to_bytes(self.common_key_index, 1)
|
||||
# Unknown data 2.
|
||||
ticket_data.write(self.unknown2)
|
||||
ticket_data += self.unknown2
|
||||
# Content access permissions.
|
||||
ticket_data.write(self.content_access_permissions)
|
||||
ticket_data += self.content_access_permissions
|
||||
# Padding (always \x00).
|
||||
ticket_data.write(b'\x00\x00')
|
||||
ticket_data += b'\x00\x00'
|
||||
# Iterate over Title Limit objects, write them back into raw data, then add them to the Ticket.
|
||||
for title_limit in range(len(self.title_limits_list)):
|
||||
title_limit_data = io.BytesIO()
|
||||
title_limit_data = b''
|
||||
# Write all fields from the title limit entry.
|
||||
title_limit_data.write(int.to_bytes(self.title_limits_list[title_limit].limit_type, 4))
|
||||
title_limit_data.write(int.to_bytes(self.title_limits_list[title_limit].maximum_usage, 4))
|
||||
# Seek to the start and write the entry to the Ticket.
|
||||
title_limit_data.seek(0x0)
|
||||
ticket_data.write(title_limit_data.read())
|
||||
title_limit_data.close()
|
||||
# Set the Ticket attribute of the object to the new raw Ticket.
|
||||
ticket_data.seek(0x0)
|
||||
ticket_data_raw = ticket_data.read()
|
||||
title_limit_data += int.to_bytes(self.title_limits_list[title_limit].limit_type, 4)
|
||||
title_limit_data += int.to_bytes(self.title_limits_list[title_limit].maximum_usage, 4)
|
||||
# Write the entry to the ticket.
|
||||
ticket_data += title_limit_data
|
||||
# Return the raw TMD for the data contained in the object.
|
||||
return ticket_data_raw
|
||||
return ticket_data
|
||||
|
||||
def get_title_id(self) -> str:
|
||||
"""
|
||||
|
@ -148,78 +148,72 @@ class TMD:
|
||||
bytes
|
||||
The full TMD file as bytes.
|
||||
"""
|
||||
# Open the stream and begin writing to it.
|
||||
with io.BytesIO() as tmd_data:
|
||||
tmd_data = b''
|
||||
# Signed blob header.
|
||||
tmd_data.write(self.blob_header)
|
||||
tmd_data += self.blob_header
|
||||
# Signing certificate issuer.
|
||||
tmd_data.write(self.issuer)
|
||||
tmd_data += self.issuer
|
||||
# TMD version.
|
||||
tmd_data.write(int.to_bytes(self.tmd_version, 1))
|
||||
tmd_data += int.to_bytes(self.tmd_version, 1)
|
||||
# Root certificate crl version.
|
||||
tmd_data.write(int.to_bytes(self.ca_crl_version, 1))
|
||||
tmd_data += int.to_bytes(self.ca_crl_version, 1)
|
||||
# Signer crl version.
|
||||
tmd_data.write(int.to_bytes(self.signer_crl_version, 1))
|
||||
tmd_data += int.to_bytes(self.signer_crl_version, 1)
|
||||
# If this is a vWii title or not.
|
||||
tmd_data.write(int.to_bytes(self.vwii, 1))
|
||||
tmd_data += int.to_bytes(self.vwii, 1)
|
||||
# IOS Title ID.
|
||||
tmd_data.write(binascii.unhexlify(self.ios_tid))
|
||||
tmd_data += binascii.unhexlify(self.ios_tid)
|
||||
# Title's Title ID.
|
||||
tmd_data.write(binascii.unhexlify(self.title_id))
|
||||
tmd_data += binascii.unhexlify(self.title_id)
|
||||
# Content type.
|
||||
tmd_data.write(binascii.unhexlify(self.content_type))
|
||||
tmd_data += binascii.unhexlify(self.content_type)
|
||||
# Group ID.
|
||||
tmd_data.write(int.to_bytes(self.group_id, 2))
|
||||
tmd_data += int.to_bytes(self.group_id, 2)
|
||||
# 2 bytes of zero for reasons.
|
||||
tmd_data.write(b'\x00\x00')
|
||||
tmd_data += b'\x00\x00'
|
||||
# Region.
|
||||
tmd_data.write(int.to_bytes(self.region, 2))
|
||||
tmd_data += int.to_bytes(self.region, 2)
|
||||
# Ratings.
|
||||
tmd_data.write(self.ratings)
|
||||
tmd_data += self.ratings
|
||||
# Reserved (all \x00).
|
||||
tmd_data.write(b'\x00' * 12)
|
||||
tmd_data += b'\x00' * 12
|
||||
# IPC mask.
|
||||
tmd_data.write(self.ipc_mask)
|
||||
tmd_data += self.ipc_mask
|
||||
# Reserved (all \x00).
|
||||
tmd_data.write(b'\x00' * 18)
|
||||
tmd_data += b'\x00' * 18
|
||||
# Access rights.
|
||||
tmd_data.write(self.access_rights)
|
||||
tmd_data += self.access_rights
|
||||
# Title version.
|
||||
title_version_high = round(self.title_version / 256)
|
||||
tmd_data.write(int.to_bytes(title_version_high, 1))
|
||||
tmd_data += int.to_bytes(title_version_high, 1)
|
||||
title_version_low = self.title_version % 256
|
||||
tmd_data.write(int.to_bytes(title_version_low, 1))
|
||||
tmd_data += int.to_bytes(title_version_low, 1)
|
||||
# Number of contents.
|
||||
tmd_data.write(int.to_bytes(self.num_contents, 2))
|
||||
tmd_data += int.to_bytes(self.num_contents, 2)
|
||||
# Boot index.
|
||||
tmd_data.write(int.to_bytes(self.boot_index, 2))
|
||||
tmd_data += int.to_bytes(self.boot_index, 2)
|
||||
# Minor version. Unused so write \x00.
|
||||
tmd_data.write(b'\x00\x00')
|
||||
tmd_data += b'\x00\x00'
|
||||
# Iterate over content records, write them back into raw data, then add them to the TMD.
|
||||
for content_record in range(self.num_contents):
|
||||
content_data = io.BytesIO()
|
||||
content_data = b''
|
||||
# Write all fields from the content record.
|
||||
content_data.write(int.to_bytes(self.content_records[content_record].content_id, 4))
|
||||
content_data.write(int.to_bytes(self.content_records[content_record].index, 2))
|
||||
content_data.write(int.to_bytes(self.content_records[content_record].content_type, 2))
|
||||
content_data.write(int.to_bytes(self.content_records[content_record].content_size, 8))
|
||||
content_data.write(binascii.unhexlify(self.content_records[content_record].content_hash))
|
||||
# Seek to the start and write the record to the TMD.
|
||||
content_data.seek(0x0)
|
||||
tmd_data.write(content_data.read())
|
||||
content_data.close()
|
||||
# Set the TMD attribute of the object to the new raw TMD.
|
||||
tmd_data.seek(0x0)
|
||||
tmd_data_raw = tmd_data.read()
|
||||
content_data += int.to_bytes(self.content_records[content_record].content_id, 4)
|
||||
content_data += int.to_bytes(self.content_records[content_record].index, 2)
|
||||
content_data += int.to_bytes(self.content_records[content_record].content_type, 2)
|
||||
content_data += int.to_bytes(self.content_records[content_record].content_size, 8)
|
||||
content_data += binascii.unhexlify(self.content_records[content_record].content_hash)
|
||||
# Write the record to the TMD.
|
||||
tmd_data += content_data
|
||||
# Return the raw TMD for the data contained in the object.
|
||||
return tmd_data_raw
|
||||
return tmd_data
|
||||
|
||||
def get_title_region(self) -> str:
|
||||
"""
|
||||
Gets the region of the TMD's associated title.
|
||||
|
||||
Can be one of several possible values:
|
||||
'JAP', 'USA', 'EUR', 'NONE', or 'KOR'.
|
||||
'JAP', 'USA', 'EUR', 'WORLD', or 'KOR'.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@ -234,7 +228,7 @@ class TMD:
|
||||
case 2:
|
||||
return "EUR"
|
||||
case 3:
|
||||
return "NONE"
|
||||
return "WORLD"
|
||||
case 4:
|
||||
return "KOR"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
import io
|
||||
import binascii
|
||||
from .shared import align_value, pad_bytes_stream
|
||||
from .shared import align_value, pad_bytes
|
||||
|
||||
|
||||
class WAD:
|
||||
@ -15,7 +15,7 @@ class WAD:
|
||||
Attributes
|
||||
----------
|
||||
wad_type : str
|
||||
The type of WAD, either ib for boot2 or Is for normal installable WADs. libWiiPy only supports Is currently.
|
||||
The type of WAD, either ib for boot2 or Is for normal installable WADs.
|
||||
wad_cert_size : int
|
||||
The size of the WAD's certificate.
|
||||
wad_crl_size : int
|
||||
@ -60,8 +60,8 @@ class WAD:
|
||||
The data for the WAD you wish to load.
|
||||
"""
|
||||
with io.BytesIO(wad_data) as wad_data:
|
||||
# Read the first 8 bytes of the file to ensure that it's a WAD. This will currently reject boot2 WADs, but
|
||||
# this tool cannot handle them correctly right now anyway.
|
||||
# Read the first 8 bytes of the file to ensure that it's a WAD. Has two possible valid values for the two
|
||||
# different types of WADs that might be encountered.
|
||||
wad_data.seek(0x0)
|
||||
wad_magic_bin = wad_data.read(8)
|
||||
wad_magic_hex = binascii.hexlify(wad_magic_bin)
|
||||
@ -140,50 +140,46 @@ class WAD:
|
||||
bytes
|
||||
The full WAD file as bytes.
|
||||
"""
|
||||
# Open the stream and begin writing data to it.
|
||||
with io.BytesIO() as wad_data:
|
||||
wad_data = b''
|
||||
# Lead-in data.
|
||||
wad_data.write(b'\x00\x00\x00\x20')
|
||||
wad_data += b'\x00\x00\x00\x20'
|
||||
# WAD type.
|
||||
wad_data.write(str.encode(self.wad_type))
|
||||
wad_data += str.encode(self.wad_type)
|
||||
# WAD version.
|
||||
wad_data.write(self.wad_version)
|
||||
wad_data += self.wad_version
|
||||
# WAD cert size.
|
||||
wad_data.write(int.to_bytes(self.wad_cert_size, 4))
|
||||
wad_data += int.to_bytes(self.wad_cert_size, 4)
|
||||
# WAD crl size.
|
||||
wad_data.write(int.to_bytes(self.wad_crl_size, 4))
|
||||
wad_data += int.to_bytes(self.wad_crl_size, 4)
|
||||
# WAD ticket size.
|
||||
wad_data.write(int.to_bytes(self.wad_tik_size, 4))
|
||||
wad_data += int.to_bytes(self.wad_tik_size, 4)
|
||||
# WAD TMD size.
|
||||
wad_data.write(int.to_bytes(self.wad_tmd_size, 4))
|
||||
wad_data += int.to_bytes(self.wad_tmd_size, 4)
|
||||
# WAD content size.
|
||||
wad_data.write(int.to_bytes(self.wad_content_size, 4))
|
||||
wad_data += int.to_bytes(self.wad_content_size, 4)
|
||||
# WAD meta size.
|
||||
wad_data.write(int.to_bytes(self.wad_meta_size, 4))
|
||||
wad_data = pad_bytes_stream(wad_data)
|
||||
wad_data += int.to_bytes(self.wad_meta_size, 4)
|
||||
wad_data = pad_bytes(wad_data)
|
||||
# Retrieve the cert data and write it out.
|
||||
wad_data.write(self.get_cert_data())
|
||||
wad_data = pad_bytes_stream(wad_data)
|
||||
wad_data += self.get_cert_data()
|
||||
wad_data = pad_bytes(wad_data)
|
||||
# Retrieve the crl data and write it out.
|
||||
wad_data.write(self.get_crl_data())
|
||||
wad_data = pad_bytes_stream(wad_data)
|
||||
wad_data += self.get_crl_data()
|
||||
wad_data = pad_bytes(wad_data)
|
||||
# Retrieve the ticket data and write it out.
|
||||
wad_data.write(self.get_ticket_data())
|
||||
wad_data = pad_bytes_stream(wad_data)
|
||||
wad_data += self.get_ticket_data()
|
||||
wad_data = pad_bytes(wad_data)
|
||||
# Retrieve the TMD data and write it out.
|
||||
wad_data.write(self.get_tmd_data())
|
||||
wad_data = pad_bytes_stream(wad_data)
|
||||
wad_data += self.get_tmd_data()
|
||||
wad_data = pad_bytes(wad_data)
|
||||
# Retrieve the meta/footer data and write it out.
|
||||
wad_data.write(self.get_meta_data())
|
||||
wad_data = pad_bytes_stream(wad_data)
|
||||
wad_data += self.get_meta_data()
|
||||
wad_data = pad_bytes(wad_data)
|
||||
# Retrieve the content data and write it out.
|
||||
wad_data.write(self.get_content_data())
|
||||
wad_data = pad_bytes_stream(wad_data)
|
||||
# Seek to the beginning and save this as the WAD data for the object.
|
||||
wad_data.seek(0x0)
|
||||
wad_data_raw = wad_data.read()
|
||||
wad_data += self.get_content_data()
|
||||
wad_data = pad_bytes(wad_data)
|
||||
# Return the raw WAD file for the data contained in the object.
|
||||
return wad_data_raw
|
||||
return wad_data
|
||||
|
||||
def get_wad_type(self) -> str:
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user