mirror of
https://github.com/MCMi460/3DS-RPC.git
synced 2025-06-19 05:55:36 -04:00
45 lines
2.0 KiB
Python
45 lines
2.0 KiB
Python
# Created by Deltaion Lee (MCMi460) on Github
|
|
# Convert `friendCode` into `principalId`
|
|
|
|
# This method took two weeks to figure out and five minutes to code
|
|
# Thank you, https://www.3dbrew.org/wiki/Principal_ID
|
|
# for essentially making my efforts have worth
|
|
# I would kiss Meleemeister (https://www.3dbrew.org/wiki/Special:Contributions/Meleemeister)
|
|
|
|
from . import *
|
|
import hashlib
|
|
|
|
class FriendCodeValidityError(Exception):
|
|
pass
|
|
|
|
class PrincipalIDValidityError(Exception):
|
|
pass
|
|
|
|
def convertFriendCodeToPrincipalId(friendCode:str) -> int:
|
|
friendCode = ''.join(filter(str.isdigit, str(friendCode))).zfill(12)
|
|
if len(friendCode) != 12: raise FriendCodeValidityError('an invalid friend code was passed') # Remove chances of friendCode being invalid
|
|
checksumPrincipal = ('%08X' % int(friendCode)).zfill(10) # Convert friendCode into hexadecimal
|
|
principalId = int(checksumPrincipal[2:], 16) # Remove most significant byte and convert to integer
|
|
checksumByte = hex(int(checksumPrincipal[:2], 16)) # Separate checksum from checksumPrincipal
|
|
if not checkPrincipalIdValidity(checksumByte, principalId): raise FriendCodeValidityError('an invalid friend code was passed')
|
|
return principalId
|
|
|
|
def checkPrincipalIdValidity(checksumByte:int, principalId:int) -> bool:
|
|
return generateChecksumByte(principalId) == checksumByte # Check to match
|
|
|
|
def generateChecksumByte(principalId:int) -> str: # https://www.3dbrew.org/wiki/FRDU:PrincipalIdToFriendCode
|
|
sha1 = hashlib.sha1(principalId.to_bytes(4, byteorder = 'little')) # Little endian sha1 of principalId
|
|
return hex(int(sha1.hexdigest()[:2], 16) >> 1) # Shift first byte to the right by one
|
|
|
|
def convertPrincipalIdtoFriendCode(principalId:int) -> int:
|
|
if not isinstance(principalId, int): raise PrincipalIDValidityError('an invalid principal id was passed')
|
|
checksumByte = generateChecksumByte(principalId)
|
|
friendCode = checksumByte + hex(principalId)
|
|
return int(friendCode.replace('0x',''), 16)
|
|
|
|
# Structure of a friendCode:
|
|
#
|
|
# (0x__ << 32) | 0x________
|
|
# Checksum PrincipalID
|
|
#
|