commit 5d3e822a35de84001182162a49c7b5563543a85c Author: tsmith372 Date: Sun Feb 8 01:58:27 2026 +0000 Initial commit diff --git a/.commit_template b/.commit_template new file mode 100644 index 0000000..179786d --- /dev/null +++ b/.commit_template @@ -0,0 +1,10 @@ + + +# ----------------------------------------------------------------- +# Checkpoint 1: This is one of the first times you are being asked +# to write your own code to help you solve a problem. Describe your +# experience. Did writing code help you understand the problem better? +# explain. +# +# Checkpoint 2: Describe the strategy you used to find the polyalphabetic +# secret word, and then to decrypt the secret message. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a4dae1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +__pycache__ diff --git a/answers.md b/answers.md new file mode 100644 index 0000000..f125e69 --- /dev/null +++ b/answers.md @@ -0,0 +1,25 @@ +# Encryption lab answers + +## Checkpoint 1 + +0. `secrets/secret0.txt` is encrypted using a Caesar Cipher. What is + its secret number? + +1. `secrets/secret1.txt` is encrypted using a Caesar Cipher. What is + its secret number? + +2. `secrets/secret2.txt` is encrypted using a Caesar Cipher. What is + its secret number? + +3. `secrets/secret3.txt` is encrypted using a Caesar Cipher. What is + its secret number? + +4. `secrets/secret4.txt` is encrypted using a Caesar Cipher. What is + its secret number? + +## Checkpoint 2 + +5. What is the polyalphabetic secret word? + +6. Decrypt this message, which was encrypted using the same secret word: + "EbZhdaV[h^bTpchhQnhig]X[VmhhRP]ftXVnRfjVY]fgtO_X](" diff --git a/ciphers/caesar.py b/ciphers/caesar.py new file mode 100644 index 0000000..ba104c1 --- /dev/null +++ b/ciphers/caesar.py @@ -0,0 +1,55 @@ +from easybits import Bits + +class CaesarCipher: + """Implements the caeser cipher. + In the caeser cipher, each character is converted into a number, + then a secret number is added to each (if the result is too large, we + loop it back around), and the result is converted back into another + character. + + int_min and int_max represent the lowest and highest allowed int values + of characters. They are set to include all the ASCII printable + characters (https://en.wikipedia.org/wiki/ASCII#Printable_character_table) + + ASCII values outside this range (for example, '\n', the newline character), + just get passed through unencrypted. + """ + + int_min = 32 + int_max = 127 + + def __init__(self, secret): + self.secret = secret + + def encrypt(self, plaintext): + "Converts a plaintext message into an encrypted ciphertext" + ciphertext = [] + for char in plaintext: + plain_int = Bits(char, encoding='ascii').int + if self.int_min <= plain_int and plain_int < self.int_max: + cipher_int = self.rotate(self.secret, plain_int) + ciphertext.append(Bits(cipher_int, length=8).ascii) + else: + ciphertext.append(char) + return ''.join(ciphertext) + + def decrypt(self, ciphertext): + "Converts an encrypted ciphertext into a plaintext message" + plaintext = [] + for char in ciphertext: + cipher_int = Bits(char, encoding='ascii').int + if self.int_min <= cipher_int and cipher_int < self.int_max: + plain_int = self.rotate(-self.secret, cipher_int) + plaintext.append(Bits(plain_int, length=8).ascii) + else: + plaintext.append(char) + return ''.join(plaintext) + + def rotate(self, secret, x): + """Adds a secret number to x. + The modulo operator (%) is used to ensure that the result + is greater than equal to int_min and less than int_max. + """ + range_size = self.int_max - self.int_min + return (x + secret - self.int_min) % range_size + self.int_min + diff --git a/ciphers/poly.py b/ciphers/poly.py new file mode 100644 index 0000000..ec4d62d --- /dev/null +++ b/ciphers/poly.py @@ -0,0 +1,69 @@ +from itertools import cycle +from easybits import Bits + +class PolyCipher: + """Implements a polyalphabetic cipher. + The polyalphabetic cipher is like a Caesar cipher except that + the secret number changes for each character to be encrypted or + decrypted. This makes frequency analysis much harder, because + each plaintext space can be encrypted as a different character. + + int_min and int_max represent the lowest and highest allowed int values + of characters. They are set to include all the ASCII printable + characters (https://en.wikipedia.org/wiki/ASCII#Printable_character_table) + + ASCII values outside this range (for example, '\n', the newline character), + just get passed through unencrypted. + """ + + int_min = 32 + int_max = 127 + + def __init__(self, secret): + self.secret = secret + + def encrypt(self, plaintext): + "Converts a plaintext message into an encrypted ciphertext" + ciphertext = [] + for char, secret_char in zip(plaintext, cycle(self.secret)): + plain_int = Bits(char, encoding='ascii').int + if self.int_min <= plain_int and plain_int < self.int_max: + secret_int = self.get_int(secret_char) + cipher_int = self.rotate(secret_int, plain_int) + ciphertext.append(Bits(cipher_int, length=8).ascii) + else: + ciphertext.append(char) + return ''.join(ciphertext) + + def decrypt(self, ciphertext): + "Converts an encrypted ciphertext into a plaintext message" + plaintext = [] + for char, secret_char in zip(ciphertext, cycle(self.secret)): + cipher_int = Bits(char, encoding='ascii').int + if self.int_min <= cipher_int and cipher_int < self.int_max: + secret_int = self.get_int(secret_char) + plain_int = self.rotate(-secret_int, cipher_int) + plaintext.append(Bits(plain_int, length=8).ascii) + else: + plaintext.append(char) + return ''.join(plaintext) + + def rotate(self, secret, x): + """Adds a secret number to x. + The modulo operator (%) is used to ensure that the result + is greater than equal to int_min and less than int_max. + """ + range_size = self.int_max - self.int_min + return (x + secret - self.int_min) % range_size + self.int_min + + def get_int(self, secret_char): + """Converts an int or a single-character string into an int. + When `secret_char` is an int, we just return it. Otherwise we + return the character's ASCII value. + """ + if isinstance(secret_char, int): + return secret_char + else: + return Bits(secret_char, encoding='ascii').int + + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..1c1352d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "lab-encryption" +version = "5.0.0" +description = "" +authors = [{ name = "Chris Proctor", email = "chris@chrisproctor.net" }] +requires-python = ">=3.10,<4.0" +readme = "README.md" +license = { text = "MIT" } +dependencies = ["easybits (>=0.1.4,<0.2.0)"] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.uv] +package = false diff --git a/secrets/secret0.txt b/secrets/secret0.txt new file mode 100644 index 0000000..4f6a3df --- /dev/null +++ b/secrets/secret0.txt @@ -0,0 +1,29 @@ +ChVTanChVTaznQda]X]VnQaXVWczn +8]ncWTnU^aTbcbn^UncWTn]XVWc*n +FWPcnX\\^acP[nWP]Sn^anThTzn +2^d[SnUaP\TncWhnUTPaUd[nbh\\Tcah. + +8]nfWPcnSXbcP]cnSTT_bn^anbZXTb|n +1da]cncWTnUXaTn^UncWX]TnThTb. +>]nfWPcnfX]VbnSPaTnWTnPb_XaT. +FWPcncWTnWP]SznSPaTnbTXiTncWTnUXaT. + +0]SnfWPcnbW^d[STazntnfWPcnPacz +2^d[SncfXbcncWTnbX]Tfbn^UncWhnWTPac. +0]SnfWT]ncWhnWTPacnQTVP]nc^nQTPc| +FWPcnSaTPSnWP]S.ntnfWPcnSaTPSnUTTc. + +FWPcncWTnWP\\Ta.nfWPcncWTnRWPX]z +8]nfWPcnUda]PRTnfPbncWhnQaPX]. +FWPcncWTnP]eX[.nfWPcnSaTPSnVaPb_| +3PaTnXcbnSTPS[hncTaa^abnR[Pb_. + +FWT]ncWTnbcPabncWaTfnS^f]ncWTXanb_TPabn +0]SnfPcTauSnWTPeT]nfXcWncWTXancTPab) +3XSnWTnb\X[TnWXbnf^aZnc^nbTT. +3XSnWTnfW^n\PSTncWTn;P\Qn\PZTncWTT. + +ChVTanChVTanQda]X]VnQaXVWcz +8]ncWTnU^aTbcbn^UncWTn]XVWc) +FWPcnX\\^acP[nWP]Sn^anThTz +3PaTnUaP\TncWhnUTPaUd[nbh\\Tcah. \ No newline at end of file diff --git a/secrets/secret1.txt b/secrets/secret1.txt new file mode 100644 index 0000000..1ed460d --- /dev/null +++ b/secrets/secret1.txt @@ -0,0 +1,19 @@ +Pof!nvtu!ibwf!b!njoe!pg!xjoufs +Up!sfhbse!uif!gsptu!boe!uif!cpvhit +Pg!uif!qjof.usfft!dsvtufe!xjui!topx< + +Boe!ibwf!cffo!dpme!b!mpoh!ujnf +Up!cfipme!uif!kvojqfst!tibhhfe!xjui!jdf- +Uif!tqsvdft!spvhi!jo!uif!ejtubou!hmjuufs + +Pg!uif!Kbovbsz!tvoN=J?A[KB[PDEJCO[L=OPg +%[OECD[PDA[H=?G[KB[I=JU[=[PDEJC[%[OKQCDPg +|J@[SEPD[KH@[SKAO[JAS[S=EH[IU[@A=N[PEIAbO[S=OPAu +0DAJ[?=J[%[@NKSJ[=J[AUAg[QJQOb@[PK[BHKSg +"KN[LNA?EKQO[BNEAJ@O[DE@[EJ[@A=PDbO[@=PAHAOO[JECDPg +|J@[SAAL[=BNAOD[HKRAbO[HKJC[OEJ?A[?=J?AHHb@[SKAg +|J@[IK=J[PDb[ATLAJOA[KB[I=JU[=[R=JEODb@[OECDPv +0DAJ[?=J[%[CNEARA[=P[CNEAR=J?AO[BKNACKJAg +|J@[DA=REHU[BNKI[SKA[PK[SKA[PAHH[KbAN +0DA[O=@[=??KQJP[KB[BKNAh>AIK=JA@[IK=Jg +3DE?D[%[JAS[L=U[=O[EB[JKP[L=E@[>ABKNAi +}QP[EB[PDA[SDEHA[%[PDEJG[KJ[PDAAg[@A=N[BNEAJ@g +|HH[HKOOAO[=NA[NAOPKNb@g[=J@[OKNNKSO[AJ@i diff --git a/secrets/secret4.txt b/secrets/secret4.txt new file mode 100644 index 0000000..b4dcedf --- /dev/null +++ b/secrets/secret4.txt @@ -0,0 +1,25 @@ +l"5&@a6(645L@(*7&/@)&"7:@3"*/@"/%@46/ +f03@"@'6--@8&&,L@5)&@#-"$,#&33*&4@806-%@3*1&/N +a5@'*345L@+645@0/&L@"@(-044:@1631-&@$-05 +a.0/(@05)&34L@3&%L@(3&&/L@)"3%@"4@"@,/05N +y06@"5&@5)"5@'*345@0/&@"/%@*54@'-&4)@8"4@48&&5 +l*,&@5)*$,&/&%@8*/&Z@46..&3G4@#-00%@8"4@*/@*5 +l&"7*/(@45"*/4@610/@5)&@50/(6&@"/%@-645@'03 +p*$,*/(N@t)&/@3&%@0/&4@*/,&%@61@"/%@5)"5@)6/(&3 +s&/5@64@065@8*5)@.*-,@$"/4L@1&"@5*/4L@+".M1054 +w)&3&@#3*"34@4$3"5$)&%@"/%@8&5@(3"44@#-&"$)&%@063@#0054N +r06/%@)":'*&-%4L@$03/'*&-%4@"/%@105"50M%3*--4 +w&@53&,,&%@"/%@1*$,&%@6/5*-@5)&@$"/4@8&3&@'6--L +u/5*-@5)&@5*/,-*/(@#0550.@)"%@#&&/@$07&3&% +w*5)@(3&&/@0/&4L@"/%@0/@501@#*(@%"3,@#-0#4@#63/&% +l*,&@"@1-"5&@0'@&:&4N@o63@)"/%4@8&3&@1&11&3&% +w*5)@5)03/@13*$,4L@063@1"-.4@45*$,:@"4@b-6&#&"3%G4N + +w&@)0"3%&%@5)&@'3&4)@#&33*&4@*/@5)&@#:3&N +b65@8)&/@5)&@#"5)@8"4@'*--&%@8&@'06/%@"@'63L +a@3"5M(3&:@'6/(64L@(-655*/(@0/@063@$"$)&N +t)&@+6*$&@8"4@45*/,*/(@500N@o/$&@0''@5)&@#64) +t)&@'36*5@'&3.&/5&%L@5)&@48&&5@'-&4)@806-%@563/@4063N +i@"-8":4@'&-5@-*,&@$3:*/(N@i5@8"4/G5@'"*3 +t)"5@"--@5)&@-07&-:@$"/'6-4@4.&-5@0'@305N +e"$)@:&"3@i@)01&%@5)&:G%@,&&1L@,/&8@5)&:@806-%@/05N diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..3bc255f --- /dev/null +++ b/uv.lock @@ -0,0 +1,98 @@ +version = 1 +requires-python = ">=3.10, <4.0" + +[[package]] +name = "bitarray" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/62/dcfac53d22ef7e904ed10a8e710a36391d2d6753c34c869b51bfc5e4ad54/bitarray-3.0.0.tar.gz", hash = "sha256:a2083dc20f0d828a7cdf7a16b20dae56aab0f43dc4f347a3b3039f6577992b03", size = 126627 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/f7/2cd02557fa9f177d54b51e6d668696266bdc1af978b5c27179449cbf5870/bitarray-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ddbf71a97ad1d6252e6e93d2d703b624d0a5b77c153b12f9ea87d83e1250e0c", size = 172224 }, + { url = "https://files.pythonhosted.org/packages/49/0a/0362089c127f2639041171803f6bf193a9e1deba72df637ebd36cb510f46/bitarray-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0e7f24a0b01e6e6a0191c50b06ca8edfdec1988d9d2b264d669d2487f4f4680", size = 123359 }, + { url = "https://files.pythonhosted.org/packages/c7/ab/a0982708b5ad92d6ec40833846ac954b57b16d9f90551a9da59e4bce79e1/bitarray-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:150b7b29c36d9f1a24779aea723fdfc73d1c1c161dc0ea14990da27d4e947092", size = 121267 }, + { url = "https://files.pythonhosted.org/packages/10/23/134ad08b9e7be3b80575fd4a50c33c79b3b360794dfc2716b6a18bf4dd60/bitarray-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8330912be6cb8e2fbfe8eb69f82dee139d605730cadf8d50882103af9ac83bb4", size = 278114 }, + { url = "https://files.pythonhosted.org/packages/c1/a1/df7d0b415207de7c6210403865a5d8a9c920209d542f552a09a02749038a/bitarray-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e56ba8be5f17dee0ffa6d6ce85251e062ded2faa3cbd2558659c671e6c3bf96d", size = 292725 }, + { url = "https://files.pythonhosted.org/packages/ec/06/03a636ac237c1860e63f037ccff35f0fec45188c94e55d9df526ee80adc3/bitarray-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffd94b4803811c738e504a4b499fb2f848b2f7412d71e6b517508217c1d7929d", size = 294722 }, + { url = "https://files.pythonhosted.org/packages/17/33/c2a7cb6f0030ea94408c84c4f80f4065b54b2bf1d4080e36fcd0b4c587a2/bitarray-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0255bd05ec7165e512c115423a5255a3f301417973d20a80fc5bfc3f3640bcb", size = 278304 }, + { url = "https://files.pythonhosted.org/packages/2c/a3/a06f76dd55d5337ff55585059058761c148da6d1e9e2bc0469d881ba5eb8/bitarray-3.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe606e728842389943a939258809dc5db2de831b1d2e0118515059e87f7bbc1a", size = 268807 }, + { url = "https://files.pythonhosted.org/packages/29/48/e8157c422542c308d6a0f5b213b21fef5779c80c00e673e2e4d7b3854d60/bitarray-3.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e89ea59a3ed86a6eb150d016ed28b1bedf892802d0ed32b5659d3199440f3ced", size = 272791 }, + { url = "https://files.pythonhosted.org/packages/ad/53/219d82592b150b580fbc479a718a7c31086627ed4599c9930408f43b6de4/bitarray-3.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cf0cc2e91dd38122dec2e6541efa99aafb0a62e118179218181eff720b4b8153", size = 264821 }, + { url = "https://files.pythonhosted.org/packages/95/08/c47b24fbb34a305531d8d0d7c15f5ab9788478384583a2614b07c2449cf8/bitarray-3.0.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2d9fe3ee51afeb909b68f97e14c6539ace3f4faa99b21012e610bbe7315c388d", size = 287871 }, + { url = "https://files.pythonhosted.org/packages/77/31/5cdf3dcf407e8fcc5ca07a06f45aaf6b0adb15f38fe6fddd03d5d1fbaf9f/bitarray-3.0.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:37be5482b9df3105bad00fdf7dc65244e449b130867c3879c9db1db7d72e508b", size = 299459 }, + { url = "https://files.pythonhosted.org/packages/b5/26/15b3630dc9bed79fc0e4a5dc92f4b1d30a872ff92f20a8b7acbb7a484bfd/bitarray-3.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0027b8f3bb2bba914c79115e96a59b9924aafa1a578223a7c4f0a7242d349842", size = 271131 }, + { url = "https://files.pythonhosted.org/packages/45/4b/1c8ba97a015d9cf44b54d4488a0005c2e9fb33ff1df38fdcf68d1cb76785/bitarray-3.0.0-cp310-cp310-win32.whl", hash = "sha256:628f93e9c2c23930bd1cfe21c634d6c84ec30f45f23e69aefe1fcd262186d7bb", size = 114230 }, + { url = "https://files.pythonhosted.org/packages/84/54/d883073137d5c245555f66c48f9518c855704b4c619aa92ddd74d6eb2c98/bitarray-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:0b655c3110e315219e266b2732609fddb0857bc69593de29f3c2ba74b7d3f51a", size = 121439 }, + { url = "https://files.pythonhosted.org/packages/61/41/321edc0fbf7e8c88552d5ff9ee07777d58e2078f2706c6478bc6651b1945/bitarray-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:44c3e78b60070389b824d5a654afa1c893df723153c81904088d4922c3cfb6ac", size = 172452 }, + { url = "https://files.pythonhosted.org/packages/48/92/4c312d6d55ac30dae96749830c9f5007a914efcb591ee0828914078eec9f/bitarray-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:545d36332de81e4742a845a80df89530ff193213a50b4cbef937ed5a44c0e5e5", size = 123502 }, + { url = "https://files.pythonhosted.org/packages/75/2c/9f3ed70ffac8e6d2b0880e132d9e5024e4ef9404a24220deca8dbd702f15/bitarray-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8a9eb510cde3fa78c2e302bece510bf5ed494ec40e6b082dec753d6e22d5d1b1", size = 121363 }, + { url = "https://files.pythonhosted.org/packages/48/e0/8ec59416aaa7ca1461a0268c0fe2fbdc8d574ac41e307980f555b773d5f6/bitarray-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e3727ab63dfb6bde00b281934e2212bb7529ea3006c0031a556a84d2268bea5", size = 285792 }, + { url = "https://files.pythonhosted.org/packages/b9/8a/fb9d76ecb44a79f02188240278574376e851d0ca81437f433c9e6481d2e5/bitarray-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2055206ed653bee0b56628f6a4d248d53e5660228d355bbec0014bdfa27050ae", size = 300848 }, + { url = "https://files.pythonhosted.org/packages/63/c5/067b688553b23e99d61ecf930abf1ad5cb5f80c2ebe6f0e2fe8ecab00b3f/bitarray-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:147542299f458bdb177f798726e5f7d39ab8491de4182c3c6d9885ed275a3c2b", size = 303027 }, + { url = "https://files.pythonhosted.org/packages/dc/46/25ebc667907736b2c5c84f4bd8260d9bece8b69719a33db5c3f3dcb281a5/bitarray-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f761184b93092077c7f6b7dad7bd4e671c1620404a76620da7872ceb576a94", size = 286125 }, + { url = "https://files.pythonhosted.org/packages/16/dd/f9a1d84965a992ff42cae5b61536e68fc944f3e31a349b690347d98fc5e0/bitarray-3.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e008b7b4ce6c7f7a54b250c45c28d4243cc2a3bbfd5298fa7dac92afda229842", size = 277111 }, + { url = "https://files.pythonhosted.org/packages/16/5b/44f298586a09beb62ec553f9efa06c8a5356d2e230e4080c72cb2800a48f/bitarray-3.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dfea514e665af278b2e1d4deb542de1cd4f77413bee83dd15ae16175976ea8d5", size = 280941 }, + { url = "https://files.pythonhosted.org/packages/28/7c/c6e157332227862727959057ba2987e6710985992b196a81f61995f21e19/bitarray-3.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:66d6134b7bb737b88f1d16478ad0927c571387f6054f4afa5557825a4c1b78e2", size = 272817 }, + { url = "https://files.pythonhosted.org/packages/b7/5d/9f7aaaaf85b5247b4a69b93af60ac7dcfff5545bf544a35517618c4244a0/bitarray-3.0.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:3cd565253889940b4ec4768d24f101d9fe111cad4606fdb203ea16f9797cf9ed", size = 295830 }, + { url = "https://files.pythonhosted.org/packages/14/1b/86dd50edd2e0612b092fe4caec3001a24298c9acab5e89a503f002ed3bef/bitarray-3.0.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4800c91a14656789d2e67d9513359e23e8a534c8ee1482bb9b517a4cfc845200", size = 307592 }, + { url = "https://files.pythonhosted.org/packages/d6/8f/45a1f1bcce5fd88d2f0bb2e1ebe8bbb55247edcb8e7a8ef06e4437e2b5e3/bitarray-3.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c2945e0390d1329c585c584c6b6d78be017d9c6a1288f9c92006fe907f69cc28", size = 278971 }, + { url = "https://files.pythonhosted.org/packages/43/2d/948c5718fe901aa58c98cef52b8898a6bea865bea7528cff6c2bc703f9f3/bitarray-3.0.0-cp311-cp311-win32.whl", hash = "sha256:c23286abba0cb509733c6ce8f4013cd951672c332b2e184dbefbd7331cd234c8", size = 114242 }, + { url = "https://files.pythonhosted.org/packages/8c/75/e921ada57bb0bcece5eb515927c031f0bc828f702b8f213639358d9df396/bitarray-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:ca79f02a98cbda1472449d440592a2fe2ad96fe55515a0447fa8864a38017cf8", size = 121524 }, + { url = "https://files.pythonhosted.org/packages/4e/2e/2e4beb2b714dc83a9e90ac0e4bacb1a191c71125734f72962ee2a20b9cfb/bitarray-3.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:184972c96e1c7e691be60c3792ca1a51dd22b7f25d96ebea502fe3c9b554f25d", size = 172152 }, + { url = "https://files.pythonhosted.org/packages/e0/1f/9ec96408c060ffc3df5ba64d2b520fd0484cb3393a96691df8f660a43b17/bitarray-3.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:787db8da5e9e29be712f7a6bce153c7bc8697ccc2c38633e347bb9c82475d5c9", size = 123319 }, + { url = "https://files.pythonhosted.org/packages/80/9f/4dd05086308bfcc84ad88c663460a8ad9f5f638f9f96eb5fa08381054db6/bitarray-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2da91ab3633c66999c2a352f0ca9ae064f553e5fc0eca231d28e7e305b83e942", size = 121242 }, + { url = "https://files.pythonhosted.org/packages/55/bb/8865b7380e9d20445bc775079f24f2279a8c0d9ee11d57c49b118d39beaf/bitarray-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7edb83089acbf2c86c8002b96599071931dc4ea5e1513e08306f6f7df879a48b", size = 287463 }, + { url = "https://files.pythonhosted.org/packages/db/8b/779119ee438090a80cbfaa49f96e783651183ab4c25b9760fe360aa7cb31/bitarray-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996d1b83eb904589f40974538223eaed1ab0f62be8a5105c280b9bd849e685c4", size = 301599 }, + { url = "https://files.pythonhosted.org/packages/41/25/78f7ba7fa8ab428767dfb722fc1ea9aac4a9813e348023d8047d8fd32253/bitarray-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4817d73d995bd2b977d9cde6050be8d407791cf1f84c8047fa0bea88c1b815bc", size = 304837 }, + { url = "https://files.pythonhosted.org/packages/f7/8d/30a448d3157b4239e635c92fc3b3789a5b87784875ca2776f65bd543d136/bitarray-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d47bc4ff9b0e1624d613563c6fa7b80aebe7863c56c3df5ab238bb7134e8755", size = 288588 }, + { url = "https://files.pythonhosted.org/packages/86/e0/c1f1b595682244f55119d55f280b5a996bcd462b702ec220d976a7566d27/bitarray-3.0.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aca0a9cd376beaccd9f504961de83e776dd209c2de5a4c78dc87a78edf61839b", size = 279002 }, + { url = "https://files.pythonhosted.org/packages/5c/4d/a17626923ad2c9d20ed1625fc5b27a8dfe2d1a3e877083e9422455ec302d/bitarray-3.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:572a61fba7e3a710a8324771322fba8488d134034d349dcd036a7aef74723a80", size = 281898 }, + { url = "https://files.pythonhosted.org/packages/50/d8/5c410580a510e669d9a28bf17675e58843236c55c60fc6dc8f8747808757/bitarray-3.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a817ad70c1aff217530576b4f037dd9b539eb2926603354fcac605d824082ad1", size = 274622 }, + { url = "https://files.pythonhosted.org/packages/e7/21/de2e8eda85c5f6a05bda75a00c22c94aee71ef09db0d5cbf22446de74312/bitarray-3.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:2ac67b658fa5426503e9581a3fb44a26a3b346c1abd17105735f07db572195b3", size = 296930 }, + { url = "https://files.pythonhosted.org/packages/13/7b/7cfad12d77db2932fb745fa281693b0031c3dfd7f2ecf5803be688cc3798/bitarray-3.0.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:12f19ede03e685c5c588ab5ed63167999295ffab5e1126c5fe97d12c0718c18f", size = 309836 }, + { url = "https://files.pythonhosted.org/packages/53/e1/5120fbb8438a0d718e063f70168a2975e03f00ce6b86e74b8eec079cb492/bitarray-3.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcef31b062f756ba7eebcd7890c5d5de84b9d64ee877325257bcc9782288564a", size = 281535 }, + { url = "https://files.pythonhosted.org/packages/73/75/8acebbbb4f85dcca73b8e91dde5d3e1e3e2317b36fae4f5b133c60720834/bitarray-3.0.0-cp312-cp312-win32.whl", hash = "sha256:656db7bdf1d81ec3b57b3cad7ec7276765964bcfd0eb81c5d1331f385298169c", size = 114423 }, + { url = "https://files.pythonhosted.org/packages/ca/56/dadae4d4351b337de6e0269001fb40f3ebe9f72222190456713d2c1be53d/bitarray-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f785af6b7cb07a9b1e5db0dea9ef9e3e8bb3d74874a0a61303eab9c16acc1999", size = 121680 }, + { url = "https://files.pythonhosted.org/packages/4f/30/07d7be4624981537d32b261dc48a16b03757cc9d88f66012d93acaf11663/bitarray-3.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7cb885c043000924554fe2124d13084c8fdae03aec52c4086915cd4cb87fe8be", size = 172147 }, + { url = "https://files.pythonhosted.org/packages/f0/e9/be1fa2828bad9cb32e1309e6dbd05adcc41679297d9e96bbb372be928e38/bitarray-3.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7814c9924a0b30ecd401f02f082d8697fc5a5be3f8d407efa6e34531ff3c306a", size = 123319 }, + { url = "https://files.pythonhosted.org/packages/22/28/33601d276a6eb76e40fe8a61c61f59cc9ff6d9ecf0b676235c02689475b8/bitarray-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bcf524a087b143ba736aebbb054bb399d49e77cf7c04ed24c728e411adc82bfa", size = 121236 }, + { url = "https://files.pythonhosted.org/packages/85/d3/f36b213ffae8f9c8e4c6f12a91e18c06570a04f42d5a1bda4303380f2639/bitarray-3.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1d5abf1d6d910599ac16afdd9a0ed3e24f3b46af57f3070cf2792f236f36e0b", size = 287395 }, + { url = "https://files.pythonhosted.org/packages/b7/1a/2da3b00d876883b05ffd3be9b1311858b48d4a26579f8647860e271c5385/bitarray-3.0.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9929051feeaf8d948cc0b1c9ce57748079a941a1a15c89f6014edf18adaade84", size = 301501 }, + { url = "https://files.pythonhosted.org/packages/88/b9/c1b5af8d1c918f1ee98748f7f7270f932f531c2259dd578c0edcf16ec73e/bitarray-3.0.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96cf0898f8060b2d3ae491762ae871b071212ded97ff9e1e3a5229e9fefe544c", size = 304804 }, + { url = "https://files.pythonhosted.org/packages/92/24/81a10862856419638c0db13e04de7cbf19938353517a67e4848c691f0b7c/bitarray-3.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab37da66a8736ad5a75a58034180e92c41e864da0152b84e71fcc253a2f69cd4", size = 288507 }, + { url = "https://files.pythonhosted.org/packages/da/70/a093af92ef7b207a59087e3b5819e03767fbdda9dd56aada3a4ee25a1fbd/bitarray-3.0.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeb79e476d19b91fd6a3439853e4e5ba1b3b475920fa40d62bde719c8af786f", size = 278905 }, + { url = "https://files.pythonhosted.org/packages/fb/40/0925c6079c4b282b16eb9085f82df0cdf1f787fb4c67fd4baca3e37acf7f/bitarray-3.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f75fc0198c955d840b836059bd43e0993edbf119923029ca60c4fc017cefa54a", size = 281909 }, + { url = "https://files.pythonhosted.org/packages/61/4b/e11754a5d34cb997250d8019b1fe555d4c06fe2d2a68b0bf7c5580537046/bitarray-3.0.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f12cc7c7638074918cdcc7491aff897df921b092ffd877227892d2686e98f876", size = 274711 }, + { url = "https://files.pythonhosted.org/packages/5b/78/39513f75423959ee2d82a82e10296b6a7bc7d880b16d714980a6752ef33b/bitarray-3.0.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dbe1084935b942fab206e609fa1ed3f46ad1f2612fb4833e177e9b2a5e006c96", size = 297038 }, + { url = "https://files.pythonhosted.org/packages/af/a2/5cb81f8773a479de7c06cc1ada36d5cc5a8ebcd8715013e1c4e01a76e84a/bitarray-3.0.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ac06dd72ee1e1b6e312504d06f75220b5894af1fb58f0c20643698f5122aea76", size = 309814 }, + { url = "https://files.pythonhosted.org/packages/03/3e/795b57c6f6eea61c47d0716e1d60219218028b1f260f7328802eac684964/bitarray-3.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:00f9a88c56e373009ac3c73c55205cfbd9683fbd247e2f9a64bae3da78795252", size = 281564 }, + { url = "https://files.pythonhosted.org/packages/f6/31/5914002ae4dd0e0079f8bccfd0647119cff364280d106108a19bd2511933/bitarray-3.0.0-cp313-cp313-win32.whl", hash = "sha256:9c6e52005e91803eb4e08c0a08a481fb55ddce97f926bae1f6fa61b3396b5b61", size = 114404 }, + { url = "https://files.pythonhosted.org/packages/76/0a/184f85a1739db841ae8fbb1d9ec028240d5a351e36abec9cd020de889dab/bitarray-3.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:cb98d5b6eac4b2cf2a5a69f60a9c499844b8bea207059e9fc45c752436e6bb49", size = 121672 }, + { url = "https://files.pythonhosted.org/packages/01/6b/405d04ed3d0e46dcc52b9f9ca98b342de5930ed87adcacb86afc830e188b/bitarray-3.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fef4e3b3f2084b4dae3e5316b44cda72587dcc81f68b4eb2dbda1b8d15261b61", size = 119755 }, + { url = "https://files.pythonhosted.org/packages/90/d8/cdfd2d41a836479db66c1d33f2615c37529458427586c8d585fec4c39c5c/bitarray-3.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e9eee03f187cef1e54a4545124109ee0afc84398628b4b32ebb4852b4a66393", size = 124105 }, + { url = "https://files.pythonhosted.org/packages/12/5d/4214bb7103fa9601332b49fc2fcef73005750581aabe7e13163ad66013cc/bitarray-3.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb5702dd667f4bb10fed056ffdc4ddaae8193a52cd74cb2cdb54e71f4ef2dd1", size = 124669 }, + { url = "https://files.pythonhosted.org/packages/fc/9b/ecfe49cf03047c8415d71ee931352b11b747525cbff9bc5db9c3592d21da/bitarray-3.0.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:666e44b0458bb2894b64264a29f2cc7b5b2cbcc4c5e9cedfe1fdbde37a8e329a", size = 126520 }, + { url = "https://files.pythonhosted.org/packages/e7/79/190bcac2a23fb5f726d0305b372f73e0bf496a43da0ace4e285e9927fcdb/bitarray-3.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c756a92cf1c1abf01e56a4cc40cb89f0ff9147f2a0be5b557ec436a23ff464d8", size = 122035 }, +] + +[[package]] +name = "easybits" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bitarray" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/fa/ba60bb2a4078da6c6de121f6b849329cc4676dcc7d897577636af7d9d9ae/easybits-0.1.4.tar.gz", hash = "sha256:2cae9c40098d9d27135c39beb1ad528409b9a744330dd30cacb8f6fd374fb9e7", size = 1840 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/2f/0e68d8caa431289a6f287941f0bd3ec13bf6f75d725c9de735d800e89f44/easybits-0.1.4-py3-none-any.whl", hash = "sha256:f0059ad99564717332dd52c1c6d417caa71195a288038268a2b93c62f5bc87f7", size = 2724 }, +] + +[[package]] +name = "lab-encryption" +version = "5.0.0" +source = { virtual = "." } +dependencies = [ + { name = "easybits" }, +] + +[package.metadata] +requires-dist = [{ name = "easybits", specifier = ">=0.1.4,<0.2.0" }]