File: //home/arjun/projects/env/lib/python3.10/site-packages/faker/providers/ssn/en_CA/__init__.py
from .. import Provider as SsnProvider
def checksum(sin):
"""
Determine validity of a Canadian Social Insurance Number.
Validation is performed using a modified Luhn Algorithm. To check
the Every second digit of the SIN is doubled and the result is
summed. If the result is a multiple of ten, the Social Insurance
Number is considered valid.
https://en.wikipedia.org/wiki/Social_Insurance_Number
"""
# Remove spaces and create a list of digits.
checksumCollection = list(sin.replace(" ", ""))
checksumCollection = [int(i) for i in checksumCollection]
# Discard the last digit, we will be calculating it later.
checksumCollection[-1] = 0
# Iterate over the provided SIN and double every second digit.
# In the case that doubling that digit results in a two-digit
# number, then add the two digits together and keep that sum.
for i in range(1, len(checksumCollection), 2):
result = checksumCollection[i] * 2
if result < 10:
checksumCollection[i] = result
else:
checksumCollection[i] = result - 10 + 1
# The appropriate checksum digit is the value that, when summed
# with the first eight values, results in a value divisible by 10
check_digit = 10 - (sum(checksumCollection) % 10)
check_digit = 0 if check_digit == 10 else check_digit
return check_digit
class Provider(SsnProvider):
# In order to create a valid SIN we need to provide a number that
# passes a simple modified Luhn Algorithm checksum.
#
# This function reverses the checksum steps to create a random
# valid nine-digit Canadian SIN (Social Insurance Number) in the
# format '### ### ###'.
def ssn(self) -> str:
# Create an array of 8 elements initialized randomly.
digits = self.generator.random.sample(range(9), 8)
# The final step of the validation requires that all of the
# digits sum to a multiple of 10. First, sum the first 8 and
# set the 9th to the value that results in a multiple of 10.
check_digit = 10 - (sum(digits) % 10)
check_digit = 0 if check_digit == 10 else check_digit
digits.append(check_digit)
# digits is now the digital root of the number we want
# multiplied by the magic number 121 212 121. The next step is
# to reverse the multiplication which occurred on every other
# element.
for i in range(1, len(digits), 2):
if digits[i] % 2 == 0:
digits[i] = digits[i] // 2
else:
digits[i] = (digits[i] + 9) // 2
# Build the resulting SIN string.
sin = ""
for i in range(0, len(digits)):
sin += str(digits[i])
# Add a space to make it conform to Canadian formatting.
if i in (2, 5):
sin += " "
# Finally return our random but valid SIN.
return sin