# READ ME
This was made for fun and learning cryptography and python.
Everything here is not for real use-cases.
Keep in mind that the functions here are probably insecure.
They went through 0 security checks, and were made without thinking of the security side of things.
# Hashing use cases
1. Detecting duplicated records.
2. Locating points that are near each other.
3. Verifying message integrity.
4. Verifying passwords.
# Installation
## pip
```
pip install cha-hashing
```
# how to use
import CHA *
```python
from CHA import FeistelN
from CHA import CHAObject
from CHA import HashMaker
from CHA import Piranha
from CHA import PEMFile
```
or just
```
from CHA import *
```
# How RA works
## The shuffle algorithm
```python
def shuffle(to_shuffle_list: list):
to_shuffle_list = to_shuffle_list.copy()
to_append_size = to_shuffle_list[0]
a = []
for i1 in range(to_append_size % len(to_shuffle_list)):
a.append(to_shuffle_list.pop(0))
to_shuffle_list.reverse()
for i2 in a:
to_shuffle_list.append(i2)
e = []
for i3, ch in enumerate(to_shuffle_list):
if i3 % 2 == 0:
e.append(to_shuffle_list.pop(i3))
for i4 in e:
to_shuffle_list.append(i4)
return to_shuffle_list
```
## Step One: Encipher
The function enciphers each letter with a letter in the shuffle list if it exists there, then shifts the letters in the shuffle list by the ord of c ** ord c each time.
```
for c in message:
for i in range(0, pow(ord(c), ord(c), len(shuffle_list))):
first = shuffle_list.pop(0)
shuffle_list.append(first)
ord_shuffle_list = [ord(c) for c in shuffle_list]
shuffled = shuffle(ord_shuffle_list)
shuffle_list = [chr(c) for c in shuffled]
if c in characters and c in shuffle_list:
index = characters.index(c)
original_message.append(shuffle_list[index])
else:
original_message.append(c)
```
## Step Two: Padding
```
binary_formatted_message = [format(ord(c), 'b') for c in original_message]
amount_to_shift = len(padding_list) - len(binary_formatted_message)
if amount_to_shift <= 0: amount_to_shift *= -1
shift_must = ord(original_message[0]) if len(original_message) > 0 else shift_must_if_om0
amount_to_shift += shift_must
binary_formatted_message.extend(padding_list)
```
## Step Three: Keying
```
key = binary_formatted_message.copy()
for i in range(0, amount_to_shift):
if times % rev_every == 0:
key.reverse()
first = key.pop(0)
key.append(first)
if key == binary_formatted_message:
first = key.pop(0)
key.append(first)
```
## Step Four: XORing
In this step we XOR the ciphertext with our key
```
binary_formatted_message = list(int(c, 2) for c in binary_formatted_message)
key = list(int(c, 2) for c in key)
xored = []
for i in range(len(binary_formatted_message)):
xored.append(binary_formatted_message[i] ^ key[i])
```
## Step Five: Repeat and shift padding
```
binary_formatted_message = list(int(c, 2) for c in binary_formatted_message)
key = list(int(c, 2) for c in key)
xored = []
for i in range(len(binary_formatted_message)):
xored.append(binary_formatted_message[i] ^ key[i])
```
## Step Six: Final
We join this large list, turn that into an int, and then we return a CHAObject object of it
```
s_xored = [str(n) for n in xored]
s = ''
for string in s_xored:
s += string.strip("-")
s = s[0:size_limit_of_0]
for i in range(pow(amount_to_shift, amount_to_shift, len(padding_list))):
intL = [int(c, 2) for c in padding_list]
padding_list = shuffle(intL)
padding_list = [format(c, 'b') for c in padding_list]
message = s
```
# CHA - Customizable Hashing Algorithm
CHA works the same way as RA, but customizable. so I'll only talk about the customization.
## message
The plaintext that enters the function.
## padding
The padding as a byte string separated by a space, like : ```'01110011 00110011 11000110'```.
this will be appended to the message
## shaffle_list
The letter shuffle list [Check the encipher step in the RA](#How-RA-works)
## size_limit_of_0
how many 0 are allowed
## rep
number of repetitions
## char_set
Additional chars used in the shuffle_list
## shift_must_if_om0
```shift_must = ord(om[0]) if len(om) > 0 else shift_must_if_om0```
## rev_every
Will preform some additional tasks with every time % $rev_every == 0
# CHAB
Like CHA but the message is in bytes
# HMAC
Syntax for hmac:
```python
from CHA import FeistelN
from CHA import CHAFHMAC
# our secret key:
secret = b'test'
# message
msg = b'secret msg'
# creating a hmac obj
hmac_obj = CHAFHMAC(secret, func=FeistelN.fRAB_with_nonce(secret))
hmac_obj.update(msg)
# getting a mac
mac = hmac_obj.hexdigest()
print(mac)
# verifying a mac
print(hmac_obj.verify(mac))
```
# Creating your own algorithm using HashMaker
## RandomShaffle
This function will help you make your own random shuffled charset (```secrets.SystemRandom().shuffle(letters)``` but with built-in langs)
returns a string
## RandomBits
This function will help you make your own random bits.
returns a string or a list
```
how_many:
how many groups of bits do you want.
```
```
group:
how many in one group, 8 for a byte
```
```
how_to_format:
Can be " " or "l".
"l" for a list.
" " for a " ".join(bits)
```
## get_CHA_args
This function will print the syntax needed. and return the padding, and shuffle key.
### _Note_
There is a chance that some padding or shuffle_key have a backdoor in them (I don't know if there really is, but probably).
# Encryption with CHA
CHA can be also used as an encryption function using the feistel cipher (see CHAF)
for example:
```
def fCHA(b):
padding, shuffle_list, size, rep, char_set, smio = CHAObject.get_RA_args()
return CHAObject.CHAB(b,padding,shuffle_list, 128, 16, '', 153)
s = input("Enter an input:\n").encode()
e = FeistelN().DE(s, 8, fCHA)
print(e)
d = FeistelN().DE(e, 8,fCHA, 'd')
print(d)
```
to make your own:
## define a function
define a function using this template
```
def fCHA(b):
padding, shuffle_list, size, rep, char_set, smio = CHAObject.get_RA_args()
return CHAObject.CHAB(b,padding,shuffle_list, 128, 16, '', 153)
```
the function needs to return bytes, here we're using CHAB with the RA args.
## Call DE
then the Feistel function uses 64 bits everytime, I configed the DE function on the FeistelN class
to do this automatically.
### mode 'e'
this will return a list of hexes
### mode 'd'
will return the string
[Feistel Cipher - Computerphile](https://www.youtube.com/watch?v=FGhj3CGxl8I)
# BlackFrog
This is an asymmetric encryption algorithm
```
Key generation:
—---------------------------------------------------------------
Let n = large prime number
Pick e such that gcd(e,n) == 1 and e < n and e is prime
d = e**-1 % n
N = n * e * random
E = e**d % N
D = d**d % n
Public key: {E,N}
Private key: {n,d,e,D}
Encryption:
—---------------------------------------------------------------
ciphertext = message*E % N
Decryption:
—---------------------------------------------------------------
message = ciphertext*D % n
```
## Generate keys
returns two keys, one public, one private
## Encrypt
Encrypts bytes with public key and returns cipher text as bytes
## Decrypt
Decrypt bytes with private key and returns message text as bytes
# Piranha
I made this cipher using the RAB-Feistel network.
I made this to learn about [modes of operation](https://www.youtube.com/watch?v=Rk0NIQfEXBA).
Right now the available modes are:
* ECB
* CBC
* CTR
* EAA (My Encrypt and Authenticate, not EAX)
```
key = b"super secret key"
msg = b'Test message'
# EBC
cipher = Piranha(key, Piranha.EBC)
c = cipher.encrypt(msg)
print(c)
cipher = Piranha(key, Piranha.EBC)
m = cipher.decrypt(c)
print(m)
# CBC
cipher = Piranha(key, Piranha.CBC)
paddedMsg = Piranha.pad(msg, Piranha.BlockSize)
c = cipher.encrypt(paddedMsg)
print(c)
cipher = Piranha(key, Piranha.CBC, iv=cipher.iv)
m = Piranha.unpad(cipher.decrypt(c))
print(m)
# CTR
cipher = Piranha(key, Piranha.CTR)
paddedMsg = Piranha.pad(msg, Piranha.BlockSize)
c = cipher.encrypt(paddedMsg)
print(c)
cipher = Piranha(key, Piranha.CTR, iv=cipher.iv)
m = Piranha.unpad(cipher.decrypt(c))
# EAA
key = b"key"
m = Piranha.pad(b'test')
cipher = Piranha(key, Piranha.EAA, data=m)
a = cipher.encrypt(m)
print(a)
cipher = Piranha(key, Piranha.EAA, iv=cipher.iv, data=a)
print(Piranha.unpad(cipher.decrypt(a)))
```
# KRY and KRHASH
I made this cipher using the KRHASH-Feistel network.
I made this to learn about [modes of operation](https://www.youtube.com/watch?v=Rk0NIQfEXBA).
Right now the available modes are:
* ECB
* CBC
* CTR
* EAA (My Encrypt and Authenticate, not EAX)
Works similar to Piranha, just replace Piranha with KRY
# CowCowModes
I made this cipher using the CowCow-sp network.
I made this to learn about [modes of operation](https://www.youtube.com/watch?v=Rk0NIQfEXBA).
Right now the available modes are:
* ECB
* CTR
* EAA (My Encrypt and Authenticate, not EAX)
Works similar to Piranha, just replace Piranha with CowCowModes
# Modes (Build you own)
Right now the available modes are:
* ECB
* CBC
* CTR
* EAA (My Encrypt and Authenticate, not EAX)
## Warning: do not init directly, use Modes.new()
# *_Notes_*:
<font color=red size=10>**This is insecure! I made everything for fun and learning! Do not use in real usecases**
</font>
PS: I know my code looks bad
Raw data
{
"_id": null,
"home_page": "https://github.com/RoyNisimov1/CHA",
"name": "cha-hashing",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "python,hashin,cha,encryption,decryption",
"author": "Roy Nisimov",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/60/d8/17c26611ed30b05340dbd81e9faf623a4d7096d3731e18be7f65d79accbe/cha_hashing-0.4.8.7.9.tar.gz",
"platform": null,
"description": "# READ ME\r\nThis was made for fun and learning cryptography and python.\r\nEverything here is not for real use-cases.\r\nKeep in mind that the functions here are probably insecure. \r\nThey went through 0 security checks, and were made without thinking of the security side of things.\r\n\r\n\r\n# Hashing use cases\r\n\r\n1. Detecting duplicated records.\r\n2. Locating points that are near each other.\r\n3. Verifying message integrity.\r\n4. Verifying passwords.\r\n\r\n# Installation\r\n## pip\r\n\r\n``` \r\npip install cha-hashing\r\n```\r\n\r\n# how to use\r\nimport CHA *\r\n```python\r\nfrom CHA import FeistelN\r\nfrom CHA import CHAObject\r\nfrom CHA import HashMaker\r\nfrom CHA import Piranha\r\nfrom CHA import PEMFile\r\n```\r\nor just \r\n```\r\nfrom CHA import *\r\n```\r\n\r\n\r\n# How RA works\r\n## The shuffle algorithm\r\n```python\r\ndef shuffle(to_shuffle_list: list):\r\n to_shuffle_list = to_shuffle_list.copy()\r\n to_append_size = to_shuffle_list[0]\r\n a = []\r\n for i1 in range(to_append_size % len(to_shuffle_list)):\r\n a.append(to_shuffle_list.pop(0))\r\n to_shuffle_list.reverse()\r\n for i2 in a:\r\n to_shuffle_list.append(i2)\r\n e = []\r\n for i3, ch in enumerate(to_shuffle_list):\r\n if i3 % 2 == 0:\r\n e.append(to_shuffle_list.pop(i3))\r\n for i4 in e:\r\n to_shuffle_list.append(i4)\r\n return to_shuffle_list\r\n```\r\n## Step One: Encipher\r\nThe function enciphers each letter with a letter in the shuffle list if it exists there, then shifts the letters in the shuffle list by the ord of c ** ord c each time. \r\n``` \r\nfor c in message:\r\n for i in range(0, pow(ord(c), ord(c), len(shuffle_list))):\r\n first = shuffle_list.pop(0)\r\n shuffle_list.append(first)\r\n ord_shuffle_list = [ord(c) for c in shuffle_list]\r\n shuffled = shuffle(ord_shuffle_list)\r\n shuffle_list = [chr(c) for c in shuffled]\r\n if c in characters and c in shuffle_list:\r\n index = characters.index(c)\r\n original_message.append(shuffle_list[index])\r\n else:\r\n original_message.append(c)\r\n```\r\n\r\n## Step Two: Padding\r\n\r\n``` \r\nbinary_formatted_message = [format(ord(c), 'b') for c in original_message]\r\n\r\n amount_to_shift = len(padding_list) - len(binary_formatted_message)\r\n if amount_to_shift <= 0: amount_to_shift *= -1\r\n shift_must = ord(original_message[0]) if len(original_message) > 0 else shift_must_if_om0\r\n amount_to_shift += shift_must\r\n binary_formatted_message.extend(padding_list)\r\n```\r\n\r\n## Step Three: Keying\r\n\r\n``` \r\nkey = binary_formatted_message.copy()\r\n for i in range(0, amount_to_shift):\r\n if times % rev_every == 0:\r\n key.reverse()\r\n first = key.pop(0)\r\n key.append(first)\r\n if key == binary_formatted_message:\r\n first = key.pop(0)\r\n key.append(first)\r\n```\r\n\r\n## Step Four: XORing\r\nIn this step we XOR the ciphertext with our key\r\n\r\n```\r\nbinary_formatted_message = list(int(c, 2) for c in binary_formatted_message)\r\nkey = list(int(c, 2) for c in key)\r\nxored = []\r\nfor i in range(len(binary_formatted_message)):\r\n xored.append(binary_formatted_message[i] ^ key[i])\r\n```\r\n## Step Five: Repeat and shift padding\r\n\r\n``` \r\nbinary_formatted_message = list(int(c, 2) for c in binary_formatted_message)\r\nkey = list(int(c, 2) for c in key)\r\nxored = []\r\nfor i in range(len(binary_formatted_message)):\r\n xored.append(binary_formatted_message[i] ^ key[i])\r\n```\r\n\r\n## Step Six: Final\r\nWe join this large list, turn that into an int, and then we return a CHAObject object of it\r\n``` \r\ns_xored = [str(n) for n in xored]\r\ns = ''\r\nfor string in s_xored:\r\n s += string.strip(\"-\")\r\ns = s[0:size_limit_of_0]\r\nfor i in range(pow(amount_to_shift, amount_to_shift, len(padding_list))):\r\n intL = [int(c, 2) for c in padding_list]\r\n padding_list = shuffle(intL)\r\n padding_list = [format(c, 'b') for c in padding_list]\r\nmessage = s\r\n```\r\n\r\n\r\n# CHA - Customizable Hashing Algorithm\r\nCHA works the same way as RA, but customizable. so I'll only talk about the customization.\r\n\r\n## message\r\nThe plaintext that enters the function.\r\n\r\n## padding\r\nThe padding as a byte string separated by a space, like : ```'01110011 00110011 11000110'```.\r\nthis will be appended to the message\r\n## shaffle_list\r\nThe letter shuffle list [Check the encipher step in the RA](#How-RA-works)\r\n\r\n## size_limit_of_0\r\nhow many 0 are allowed\r\n\r\n## rep\r\nnumber of repetitions\r\n\r\n## char_set\r\nAdditional chars used in the shuffle_list\r\n\r\n## shift_must_if_om0\r\n```shift_must = ord(om[0]) if len(om) > 0 else shift_must_if_om0```\r\n\r\n## rev_every\r\nWill preform some additional tasks with every time % $rev_every == 0\r\n\r\n# CHAB\r\nLike CHA but the message is in bytes\r\n\r\n# HMAC\r\nSyntax for hmac:\r\n```python\r\nfrom CHA import FeistelN\r\nfrom CHA import CHAFHMAC\r\n# our secret key:\r\n\r\nsecret = b'test'\r\n# message\r\nmsg = b'secret msg'\r\n# creating a hmac obj\r\nhmac_obj = CHAFHMAC(secret, func=FeistelN.fRAB_with_nonce(secret))\r\nhmac_obj.update(msg)\r\n# getting a mac\r\nmac = hmac_obj.hexdigest()\r\nprint(mac)\r\n# verifying a mac\r\nprint(hmac_obj.verify(mac))\r\n```\r\n\r\n# Creating your own algorithm using HashMaker\r\n\r\n## RandomShaffle\r\nThis function will help you make your own random shuffled charset (```secrets.SystemRandom().shuffle(letters)``` but with built-in langs)\r\nreturns a string\r\n\r\n## RandomBits\r\nThis function will help you make your own random bits.\r\nreturns a string or a list\r\n\r\n```\r\nhow_many:\r\nhow many groups of bits do you want.\r\n```\r\n```\r\ngroup:\r\nhow many in one group, 8 for a byte\r\n```\r\n```\r\nhow_to_format:\r\nCan be \" \" or \"l\". \r\n\"l\" for a list.\r\n\" \" for a \" \".join(bits)\r\n```\r\n## get_CHA_args\r\nThis function will print the syntax needed. and return the padding, and shuffle key.\r\n\r\n### _Note_\r\nThere is a chance that some padding or shuffle_key have a backdoor in them (I don't know if there really is, but probably). \r\n\r\n# Encryption with CHA\r\n\r\nCHA can be also used as an encryption function using the feistel cipher (see CHAF)\r\n\r\n\r\nfor example:\r\n```\r\n def fCHA(b):\r\n padding, shuffle_list, size, rep, char_set, smio = CHAObject.get_RA_args()\r\n return CHAObject.CHAB(b,padding,shuffle_list, 128, 16, '', 153)\r\n s = input(\"Enter an input:\\n\").encode()\r\n e = FeistelN().DE(s, 8, fCHA)\r\n print(e)\r\n d = FeistelN().DE(e, 8,fCHA, 'd')\r\n print(d)\r\n```\r\n\r\nto make your own:\r\n\r\n## define a function\r\ndefine a function using this template\r\n```\r\n def fCHA(b):\r\n padding, shuffle_list, size, rep, char_set, smio = CHAObject.get_RA_args()\r\n return CHAObject.CHAB(b,padding,shuffle_list, 128, 16, '', 153)\r\n```\r\n\r\nthe function needs to return bytes, here we're using CHAB with the RA args. \r\n\r\n## Call DE\r\n\r\nthen the Feistel function uses 64 bits everytime, I configed the DE function on the FeistelN class\r\nto do this automatically.\r\n### mode 'e'\r\nthis will return a list of hexes\r\n### mode 'd'\r\nwill return the string\r\n\r\n[Feistel Cipher - Computerphile](https://www.youtube.com/watch?v=FGhj3CGxl8I)\r\n\r\n# BlackFrog\r\nThis is an asymmetric encryption algorithm\r\n``` \r\nKey generation:\r\n\u00e2\u20ac\u201d---------------------------------------------------------------\r\n\r\nLet n = large prime number\r\n\r\nPick e such that gcd(e,n) == 1 and e < n and e is prime\r\nd = e**-1 % n\r\nN = n * e * random\r\nE = e**d % N\r\nD = d**d % n\r\n\r\nPublic key: {E,N}\r\nPrivate key: {n,d,e,D}\r\n\r\nEncryption:\r\n\u00e2\u20ac\u201d---------------------------------------------------------------\r\n\r\nciphertext = message*E % N\r\n\r\nDecryption:\r\n\u00e2\u20ac\u201d---------------------------------------------------------------\r\nmessage = ciphertext*D % n\r\n```\r\n## Generate keys\r\nreturns two keys, one public, one private\r\n\r\n## Encrypt\r\n\r\nEncrypts bytes with public key and returns cipher text as bytes\r\n\r\n## Decrypt\r\n\r\nDecrypt bytes with private key and returns message text as bytes\r\n\r\n\r\n# Piranha\r\nI made this cipher using the RAB-Feistel network.\r\n\r\nI made this to learn about [modes of operation](https://www.youtube.com/watch?v=Rk0NIQfEXBA).\r\n\r\nRight now the available modes are:\r\n* ECB\r\n* CBC\r\n* CTR\r\n* EAA (My Encrypt and Authenticate, not EAX)\r\n\r\n``` \r\n key = b\"super secret key\"\r\n msg = b'Test message'\r\n # EBC\r\n cipher = Piranha(key, Piranha.EBC)\r\n c = cipher.encrypt(msg)\r\n print(c)\r\n cipher = Piranha(key, Piranha.EBC)\r\n m = cipher.decrypt(c)\r\n print(m)\r\n\r\n # CBC\r\n cipher = Piranha(key, Piranha.CBC)\r\n paddedMsg = Piranha.pad(msg, Piranha.BlockSize)\r\n c = cipher.encrypt(paddedMsg)\r\n print(c)\r\n cipher = Piranha(key, Piranha.CBC, iv=cipher.iv)\r\n m = Piranha.unpad(cipher.decrypt(c))\r\n print(m)\r\n\r\n # CTR\r\n cipher = Piranha(key, Piranha.CTR)\r\n paddedMsg = Piranha.pad(msg, Piranha.BlockSize)\r\n c = cipher.encrypt(paddedMsg)\r\n print(c)\r\n cipher = Piranha(key, Piranha.CTR, iv=cipher.iv)\r\n m = Piranha.unpad(cipher.decrypt(c))\r\n \r\n # EAA\r\n key = b\"key\"\r\n m = Piranha.pad(b'test')\r\n cipher = Piranha(key, Piranha.EAA, data=m)\r\n a = cipher.encrypt(m)\r\n print(a)\r\n cipher = Piranha(key, Piranha.EAA, iv=cipher.iv, data=a)\r\n print(Piranha.unpad(cipher.decrypt(a)))\r\n```\r\n\r\n# KRY and KRHASH\r\nI made this cipher using the KRHASH-Feistel network.\r\n\r\nI made this to learn about [modes of operation](https://www.youtube.com/watch?v=Rk0NIQfEXBA).\r\n\r\nRight now the available modes are:\r\n* ECB\r\n* CBC\r\n* CTR\r\n* EAA (My Encrypt and Authenticate, not EAX)\r\n\r\nWorks similar to Piranha, just replace Piranha with KRY\r\n\r\n# CowCowModes\r\nI made this cipher using the CowCow-sp network.\r\n\r\nI made this to learn about [modes of operation](https://www.youtube.com/watch?v=Rk0NIQfEXBA).\r\n\r\nRight now the available modes are:\r\n* ECB\r\n* CTR\r\n* EAA (My Encrypt and Authenticate, not EAX)\r\n\r\nWorks similar to Piranha, just replace Piranha with CowCowModes\r\n\r\n\r\n\r\n# Modes (Build you own)\r\n\r\nRight now the available modes are:\r\n* ECB\r\n* CBC\r\n* CTR\r\n* EAA (My Encrypt and Authenticate, not EAX)\r\n\r\n## Warning: do not init directly, use Modes.new()\r\n\r\n\r\n\r\n\r\n# *_Notes_*:\r\n\r\n<font color=red size=10>**This is insecure! I made everything for fun and learning! Do not use in real usecases**\r\n</font>\r\n\r\nPS: I know my code looks bad\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A hashing and encryption with Customizable Hashing Algorithm CHA, WARNING: DO NOT USE IN REAL USE CASES! THIS WAS MADE JUST FOR FUN!",
"version": "0.4.8.7.9",
"project_urls": {
"Homepage": "https://github.com/RoyNisimov1/CHA"
},
"split_keywords": [
"python",
"hashin",
"cha",
"encryption",
"decryption"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d024ec0ad1d276b36b6bb1b6739cbb8efcde6bf1b4150067b584a26fd084f3e2",
"md5": "4c84cdc30fb3b40fc71373228edbe5e4",
"sha256": "d359f586774b62071958109abf5e453fd530040f84a8a884f0f902472858b563"
},
"downloads": -1,
"filename": "cha_hashing-0.4.8.7.9-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4c84cdc30fb3b40fc71373228edbe5e4",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 26988,
"upload_time": "2023-12-21T17:18:03",
"upload_time_iso_8601": "2023-12-21T17:18:03.015587Z",
"url": "https://files.pythonhosted.org/packages/d0/24/ec0ad1d276b36b6bb1b6739cbb8efcde6bf1b4150067b584a26fd084f3e2/cha_hashing-0.4.8.7.9-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "60d817c26611ed30b05340dbd81e9faf623a4d7096d3731e18be7f65d79accbe",
"md5": "195eef43e2156e777ab92c3511053e61",
"sha256": "571ec3ab18a2e64ebdf2dc700b1c6d2d5ddc408d2351b2f8276969dec3958742"
},
"downloads": -1,
"filename": "cha_hashing-0.4.8.7.9.tar.gz",
"has_sig": false,
"md5_digest": "195eef43e2156e777ab92c3511053e61",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 23599,
"upload_time": "2023-12-21T17:18:08",
"upload_time_iso_8601": "2023-12-21T17:18:08.510845Z",
"url": "https://files.pythonhosted.org/packages/60/d8/17c26611ed30b05340dbd81e9faf623a4d7096d3731e18be7f65d79accbe/cha_hashing-0.4.8.7.9.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-12-21 17:18:08",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "RoyNisimov1",
"github_project": "CHA",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "cha-hashing"
}