-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlove.py
43 lines (34 loc) · 2.04 KB
/
love.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 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)
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)[2:].zfill(8)
return int(friendCode.replace('0x',''), 16)
# Structure of a friendCode:
#
# (0x__ << 32) | 0x________
# Checksum PrincipalID
#