From 6daf07d2003828c3cc99ecd28da9ad715f6eff30 Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Mon, 15 Apr 2019 22:13:21 -0400 Subject: [PATCH 01/20] Create base64encode.py --- base64encode.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 base64encode.py diff --git a/base64encode.py b/base64encode.py new file mode 100644 index 0000000..ae8d2b0 --- /dev/null +++ b/base64encode.py @@ -0,0 +1,40 @@ +import math # required +import secrets ## optional for future use +import string # required +import binascii # required + +Author: Steven Hatzakis @2018, Licensed under Apache 2.0 + +#test binary data string: 0b010010010111011111001110010111011101001110001101001011100010011100011101001110011111001110010111010001001010011101100011001010010100010010011100111001000010000000000001001000 + +#test string as hex: '0x125df39774e34b89c74e7ce5d129d8ca512739080048' + +#test string result :'INVENTEDBYSTEVENHATZAKIS@2018' + +## legacy notes: #FIX: LEADING ZEROS LOST (i.e.w/ test string 0x064ce8c835f4d374e04e33244beccad0) +#also, even when no leading zero in string, the leading zeroes of the actual base64 character are discarded, +#as the encoding appears to happen from right to left, see this test string where leading zeroes of +# first char 2 are discarded, and last char is N 0xb13ae7e331ce9dfa59799e95ee8dc117 + +def base64en(address_hex): # important never to rename base64en to "base64" which can corrupt the Python installation. + alphabet = string.digits+string.ascii_uppercase+string.punctuation + b64_string = '' + # Get the number of leading zeros and convert hex to decimal + leading_zeros = len(str(address_hex))-2 #len(str(address_hex)) - len(str(address_hex.lstrip('0'))) + # Convert hex to decimal + address_int = int(address_hex) + # Append digits to the start of string + while address_int > 0: + digit = address_int % 64 + digit_char = alphabet[digit] + b64_string = digit_char + b64_string + address_int //= 64 + # Add '1' for each 2 leading zeros + #ones = leading_zeros // 8 + #for one in range(ones): + # b64_string = '1' + b64_string + return b64_string +hexer=int(input('enter hex with pad'),16) +print(base64en(hexer)) +print("The above is this many char's long: ",len(str((base64en(hexer))))) + From 55387e323dcaa0c82097966e550ec7c027c977cd Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Mon, 15 Apr 2019 22:47:33 -0400 Subject: [PATCH 02/20] Add # to line 6 comment command "#" tag was missing in front of authorship on line 6 --- base64encode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base64encode.py b/base64encode.py index ae8d2b0..b46ee5e 100644 --- a/base64encode.py +++ b/base64encode.py @@ -3,7 +3,7 @@ import string # required import binascii # required -Author: Steven Hatzakis @2018, Licensed under Apache 2.0 +#Author: Steven Hatzakis @2018, Licensed under Apache 2.0 #test binary data string: 0b010010010111011111001110010111011101001110001101001011100010011100011101001110011111001110010111010001001010011101100011001010010100010010011100111001000010000000000001001000 From 0348d463dfca9ab7eb19f0661700fb3ad7145d69 Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Mon, 15 Apr 2019 22:53:12 -0400 Subject: [PATCH 03/20] Create base64decode.py --- base64decode.py | 159 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 base64decode.py diff --git a/base64decode.py b/base64decode.py new file mode 100644 index 0000000..6e79bdf --- /dev/null +++ b/base64decode.py @@ -0,0 +1,159 @@ +import string +import binascii +import math +import secrets + +#Author: Steven Hatzakis @2018, Licensed under Apache 2.0 + +# NOTE: The initial version of this application is not yet functional and requires a code fix/rewrite in order to properly decode using the sample test string below. + +# Example Test string target to decode: hello world +# Each letter decodes to respective 6-bit group: `"010001","001110","010101","010101","011000"," ", "100000","011000","011011","010101","001101", +# Each Word as Continous string `"010001001110010101010101011000" "100000011000011011010101001101" +# Concatenation of both words into one string: `"010001001110010101010101011000100000011000011011010101001101" +# Converted binary string to hex: `0x44e55562061b54d` + + +arbitrarystring=format(secrets.randbits(139),'139b') +#arbitrarystring=str(arbitrarystring) +print("0b"+arbitrarystring) +print("As hex:",hex(int(arbitrarystring, 2))) +arbitrarystring=arbitrarystring[:132] + + +print("first 132 bits:",arbitrarystring) +s=str(arbitrarystring) +groups= [s[i:i+6] for i in range(0,len(s),6)] + +print(groups) +padgroup=[s[i:i+6] for i in range(0,len(s),6)] + +#print(padgroup) + + +base64library=["0", +"1", +"2", +"3", +"4", +"5", +"6", +"7", +"8", +"9", +"A", +"B", +"C", +"D ", +"E", +"F", +"G", +"H", +"I", +"J", +"K", +"L", +"M", +"N", +"O", +"P", +"Q", +"R", +"S", +"T", +"U", +"V", +"W", +"X", +"Y", +"Z", +"!", +'"', +"#", +"$", +"%", +"&", +"'", +"(", +")", +"*", +"+", +",", +"-", +".", +"/", +":", +";", +"<", +"=", +">", +"?", +"@", +"[", +"\\", +"]", +"^", +"_", +"`"] + +## Note/CONSIDERATION: Last four punctuation characters "{|}`" have been omitted from the above list, and even though they exists in the encoder python app it never appears in results (perhaps should be added here so a warning/error would trigger if those values ever appear in results or when entered into a decoder. + +#OLD jolly=[padgroup[i:i+6] for i in range(0,len(base64library[0]),6)] +index=[padgroup[i:i+22] for i in range(0,len(str(padgroup[0])),6)] +print('Index:', index) + +First=int((padgroup[0]),2) + +#First=bin(First) + +print(base64library[First]) + +Second=int(padgroup[1],2) + +print(base64library[Second]) +Third=int(padgroup[2],2) +print(base64library[Third]) +Fourth=int(padgroup[3],2) +print(base64library[Fourth]) +Fifth=int(padgroup[4],2) +print(base64library[Fifth]) +Sixth=int(padgroup[5],2) +print(base64library[Sixth]) +Seventh=int(padgroup[6],2) +print(base64library[Seventh]) +Eigth=int(padgroup[7],2) +print(base64library[Eigth]) +Ninth=int(padgroup[8],2) +print(base64library[Ninth]) +Tenth=int(padgroup[9],2) +print(base64library[Tenth]) +Eleventh=int(padgroup[10],2) +print(base64library[Eleventh]) +Twelfth=int(padgroup[11],2) +print(base64library[Twelfth]) +Thirteenth=int(padgroup[12],2) +print(base64library[Thirteenth]) +Fourteenth=int(padgroup[13],2) +print(base64library[Fourteenth]) +Fifteenth=int(padgroup[14],2) +print(base64library[Fifteenth]) +Sixteenth=int(padgroup[15],2) +print(base64library[Sixteenth]) +Seventeenth=int(padgroup[16],2) +print(base64library[Seventeenth]) +Eighteenth=int(padgroup[17],2) +print(base64library[Eighteenth]) +Nineteenth=int(padgroup[18],2) +print(base64library[Nineteenth]) +Twentieth=int(padgroup[19],2) +print(base64library[Twentieth]) +TwentyFirst=int(padgroup[20],2) +print(base64library[TwentyFirst]) +TwentySecond=int(padgroup[21],2) +print(base64library[TwentySecond]) + +## + +print(base64library[First],base64library[Second],base64library[Third],base64library[Fourth],base64library[Fifth],base64library[Sixth],base64library[Seventh],base64library[Eigth],base64library[Ninth],base64library[Tenth],base64library[Eleventh],base64library[Twelfth],base64library[Thirteenth],base64library[Fourteenth],base64library[Fifteenth],base64library[Sixteenth],base64library[Seventeenth],base64library[Eighteenth],base64library[Nineteenth],base64library[Twentieth],base64library[TwentyFirst],base64library[TwentySecond]) +print(base64library[First]+base64library[Second]+base64library[Third]+base64library[Fourth]+base64library[Fifth]+base64library[Sixth]+base64library[Seventh]+base64library[Eigth]+base64library[Ninth]+base64library[Tenth]+base64library[Eleventh]+base64library[Twelfth]+base64library[Thirteenth]+base64library[Fourteenth]+base64library[Fifteenth]+base64library[Sixteenth]+base64library[Seventeenth]+base64library[Eighteenth]+base64library[Nineteenth]+base64library[Twentieth]+base64library[TwentyFirst]+base64library[TwentySecond]) +print("Length of initial ent as hex:",len(hex(int("0b"+arbitrarystring, 2)))) From 957fea691782f619850e6157f35f5d70eff9a1d9 Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Mon, 15 Apr 2019 23:11:01 -0400 Subject: [PATCH 04/20] Added Bip39 link as reference https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3c3632f..c0393f5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hatnotation -> Hatnotation is short for the *Hatzakis Base 64 notation system* which is a method to encode/decode arbitrary binary strings of data, invented by Steven Hatzakis and open-sourced here under Apache License 2.0 https://github.com/hatgit/hatnotation/blob/master/LICENSE. +> Hatnotation is short for the *Hatzakis Base 64 notation system* which is a method to encode/decode arbitrary binary strings of data, invented by Steven Hatzakis and open-sourced here under [Apache License 2.0] (https://github.com/hatgit/hatnotation/blob/master/LICENSE).
[Use of Hatnotation is subject to Apache License 2.0 ] https://github.com/hatgit/hatnotation/blob/master/LICENSE
@@ -17,7 +17,7 @@ This software is still in its experimental phase and should not be relied upon f
 
 ## Background on Mnemonics (private keys) and Human vs Machine-readable code
 
-Mnemonics (aka recovery phrases) are used in many popular crypto wallet applciations including BIP39 (which follows a specific wordlist and checksum requirement, among other steps for wallet derivation such as BIP32, BIP44) enable a user to backup their initial entropy in human-readable format. 
+Mnemonics (aka recovery phrases) are used in many popular crypto wallet applciations including [BIP39] (https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) (which follows a specific wordlist and checksum requirement, among other steps for wallet derivation such as BIP32, BIP44) enable a user to backup their initial entropy in human-readable format. 
 
 For example, instead of a user having to backup a string of 128 bits or their private key, they can simply store the encoded mnemonic which represents those bits or a private key. 
 

From 1d27b4a876821cb90cd92734ff3eec7a6e8d9408 Mon Sep 17 00:00:00 2001
From: Steven Hatzakis 
Date: Tue, 16 Apr 2019 10:31:07 -0400
Subject: [PATCH 05/20] Update README.md

---
 README.md | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index c0393f5..28e14f0 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
 
## Purpose -An encoding/decoding method that allows users to compress their human-readable data into fewer humand-readable characters than other popular notation systems, for any arbitrary underlying machine-readable binary string. +An encoding/decoding method that allows users to compress their human-readable data into fewer human-readable characters than other popular notation systems, for any arbitrary underlying machine-readable binary string. ## Warning: @@ -32,7 +32,7 @@ For example, instead of a user having to backup a string of 128 bits or their pr |Total Words |`132/11 = 12 words` |`264/11 = 24 words` | |----------------|-------------------------------|-----------------------------| -In terms of actual pre-image resistance, the initial entropy should be generated in a cryptographically-secure manner that is pre-image resistant and resistant to other attacks, such as outlined in the W3C Cryptography API or via the "secrets" module in Python), and the psuedo-random binary string that results will be that is machine-readable where the purpose of encoding it into a mnemonic is to make it easier to notate, recite, read, and write, compared to binary (machine-readable). +In terms of actual pre-image resistance, the initial entropy should be generated in a cryptographically-secure manner that is pre-image resistant and resistant to other attacks, such as outlined in the W3C Cryptography API or via the "secrets" module in Python), and the psuedo-random binary string that results will be machine-readable where the purpose of encoding it into a mnemonic is to make it easier to notate, recite, read, and write, (i.e. human-readable) compared to binary (machine-readable). @@ -62,12 +62,12 @@ The Hatnotation system is *not intended to be an alternative to human-readable m Just as a mnemonic that represents a 132 bits of some initial entropy should convey 128 bits of security if generated properly, as the last 4 bits are deterministically derived from the hash-based checksum computation (hashing the initial entropy as a byte array). Those same 132 bits can be encoded using the Hatnotation system which will result in 22 characters, sourced from the 64 character library. Mathematically, 64^22 == 2^132, hence why there is no information/security loss, for example. ### Lemma -For any arbitrary binary (base-2) string x of length n, after hatnotation is applied to x, the length n = ((x - (x % 6))/6)+(x %6, optionally in some cases depending on how the encoder/decoder is constructed). Optimal compression will occur when the [COMPLETE THIS SECTION] +For any arbitrary binary (base-2) string x of length n, after hatnotation is applied to x, the length n = ((x - (x % 6))/6)+(x %6, optionally in some cases depending on how the encoder/decoder is constructed). Optimal compression will occur when the x modulo 6 is equal to zero, and least optimum when x modulo 6 is equal to 5 (The assumption in this last sentence should be checked). Below are two examples of when notation is optimum, using 132 bits and 264 bits as an example, and which are standard bit-lengths for the underlying entropy that represents 12-word or 24-word mnemonics used with cryto wallets. -- `(128-(128 % 6)) / 6 == 21 == 2^128` -- `(132-(132 % 6)) / 6 == 22 == 2^132` -- `(256-(256 % 6)) / 6 == 42 == 2^256` -- `(264-(264 % 6)) / 6 == 44 == 2^264` + +- `(64^((132-(132 % 6)) / 6) == 2^132` + +- `(64^((264-(264 % 6)) / 6) == 2^264` | Private Key |12-word mnemonic |24-word mnemonic | From 29cfe7c36f3eea505c8aa19945169f361e818c23 Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Tue, 16 Apr 2019 10:42:00 -0400 Subject: [PATCH 06/20] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 28e14f0..57d59f5 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,9 @@ Python 3 or higher ## Reources: +Other base64 encoding schemes: https://en.wikipedia.org/wiki/Base64 +Notational conventions: https://tools.ietf.org/html/rfc2822 + ## Roadmap/Plans: From aa426161bb8bbdbf5798f14c04e4e66ad8eb6df1 Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Tue, 16 Apr 2019 10:54:54 -0400 Subject: [PATCH 07/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57d59f5..a0b270e 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ The Hatnotation system is *not intended to be an alternative to human-readable m Just as a mnemonic that represents a 132 bits of some initial entropy should convey 128 bits of security if generated properly, as the last 4 bits are deterministically derived from the hash-based checksum computation (hashing the initial entropy as a byte array). Those same 132 bits can be encoded using the Hatnotation system which will result in 22 characters, sourced from the 64 character library. Mathematically, 64^22 == 2^132, hence why there is no information/security loss, for example. ### Lemma -For any arbitrary binary (base-2) string x of length n, after hatnotation is applied to x, the length n = ((x - (x % 6))/6)+(x %6, optionally in some cases depending on how the encoder/decoder is constructed). Optimal compression will occur when the x modulo 6 is equal to zero, and least optimum when x modulo 6 is equal to 5 (The assumption in this last sentence should be checked). Below are two examples of when notation is optimum, using 132 bits and 264 bits as an example, and which are standard bit-lengths for the underlying entropy that represents 12-word or 24-word mnemonics used with cryto wallets. +For any arbitrary binary (base-2) string x of length n, after hatnotation is applied to x, the length n = ((x - (x % 6))/6)+(x %6, optionally in some cases depending on how the encoder/decoder is constructed). Optimal compression will occur when the x modulo 6 is equal to zero, and least optimum when x modulo 6 is equal to 5 (The assumption in this last sentence should be checked). Below are two examples of when notation is optimum, using 132 bits and 264 bits as an example, and which are standard bit-lengths for the underlying entropy that represents 12-word or 24-word mnemonics used with crypto wallets. - `(64^((132-(132 % 6)) / 6) == 2^132` From 565534629c8c0a25d01f4b08f3f5ec6fcc2ca0dc Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Tue, 16 Apr 2019 11:02:01 -0400 Subject: [PATCH 08/20] Update README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0b270e..11e908a 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ For example, instead of a user having to backup a string of 128 bits or their pr |Total Words |`132/11 = 12 words` |`264/11 = 24 words` | |----------------|-------------------------------|-----------------------------| -In terms of actual pre-image resistance, the initial entropy should be generated in a cryptographically-secure manner that is pre-image resistant and resistant to other attacks, such as outlined in the W3C Cryptography API or via the "secrets" module in Python), and the psuedo-random binary string that results will be machine-readable where the purpose of encoding it into a mnemonic is to make it easier to notate, recite, read, and write, (i.e. human-readable) compared to binary (machine-readable). +In terms of actual pre-image resistance, the initial entropy should be generated in a cryptographically-secure manner that is pre-image resistant and resistant to other attacks, such as outlined in the [W3C Cryptography API](https://www.w3.org/TR/WebCryptoAPI/) or via the [secrets](https://docs.python.org/3/library/secrets.html) module in Python), and the psuedo-random binary string that results will be machine-readable where the purpose of encoding it into a mnemonic is to make it easier to notate, recite, read, and write, (i.e. human-readable) compared to binary (machine-readable). @@ -62,7 +62,9 @@ The Hatnotation system is *not intended to be an alternative to human-readable m Just as a mnemonic that represents a 132 bits of some initial entropy should convey 128 bits of security if generated properly, as the last 4 bits are deterministically derived from the hash-based checksum computation (hashing the initial entropy as a byte array). Those same 132 bits can be encoded using the Hatnotation system which will result in 22 characters, sourced from the 64 character library. Mathematically, 64^22 == 2^132, hence why there is no information/security loss, for example. ### Lemma -For any arbitrary binary (base-2) string x of length n, after hatnotation is applied to x, the length n = ((x - (x % 6))/6)+(x %6, optionally in some cases depending on how the encoder/decoder is constructed). Optimal compression will occur when the x modulo 6 is equal to zero, and least optimum when x modulo 6 is equal to 5 (The assumption in this last sentence should be checked). Below are two examples of when notation is optimum, using 132 bits and 264 bits as an example, and which are standard bit-lengths for the underlying entropy that represents 12-word or 24-word mnemonics used with crypto wallets. +For any arbitrary binary (base-2) string x of length n, after hatnotation is applied to x, the length n = ((x - (x % 6))/6)+(x %6, optionally in some cases depending on how the encoder/decoder is constructed). Optimal compression will occur when the x modulo 6 is equal to zero, and least optimum when x modulo 6 is equal to 5 (The assumption in this last sentence should be checked). + +Below are two examples of when notation is optimum, using 132 bits and 264 bits as an example, and which are standard bit-lengths for the underlying entropy that represents 12-word or 24-word mnemonics used with crypto wallets. - `(64^((132-(132 % 6)) / 6) == 2^132` @@ -174,6 +176,8 @@ Python 3 or higher ## Tests: + + ## Reources: Other base64 encoding schemes: https://en.wikipedia.org/wiki/Base64 From 1238949683c0d5b8683f90e7302b0d65e81f4cbb Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Tue, 16 Apr 2019 11:41:45 -0400 Subject: [PATCH 09/20] Update README.md --- README.md | 189 +----------------------------------------------------- 1 file changed, 1 insertion(+), 188 deletions(-) diff --git a/README.md b/README.md index 11e908a..342bcd9 100644 --- a/README.md +++ b/README.md @@ -1,188 +1 @@ -# Hatnotation - -> Hatnotation is short for the *Hatzakis Base 64 notation system* which is a method to encode/decode arbitrary binary strings of data, invented by Steven Hatzakis and open-sourced here under [Apache License 2.0] (https://github.com/hatgit/hatnotation/blob/master/LICENSE). - -
-
[Use of Hatnotation is subject to Apache License 2.0 ] https://github.com/hatgit/hatnotation/blob/master/LICENSE
-
-
- -## Purpose -An encoding/decoding method that allows users to compress their human-readable data into fewer human-readable characters than other popular notation systems, for any arbitrary underlying machine-readable binary string. - - -## Warning: - -This software is still in its experimental phase and should not be relied upon for production. - -## Background on Mnemonics (private keys) and Human vs Machine-readable code - -Mnemonics (aka recovery phrases) are used in many popular crypto wallet applciations including [BIP39] (https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) (which follows a specific wordlist and checksum requirement, among other steps for wallet derivation such as BIP32, BIP44) enable a user to backup their initial entropy in human-readable format. - -For example, instead of a user having to backup a string of 128 bits or their private key, they can simply store the encoded mnemonic which represents those bits or a private key. - -> Note: While the word "private key" is usually associated with public/private key-pairs in cryptogrpahy, for the purpose of this Readme.md file, the use of private key refers to the master private key (initial entropy) for a crypto vault (within which accounts and private keys are dervived) which can also be considered a pre-image of the mnemonic. - - -| |12-word mnemonic |24-word mnemonic | -|----------------|-------------------------------|-----------------------------| -|Initial Entropy (security) |`128 bits` |`256 bits` | -|Checksum |`4 bits` |`8 bits` | -|Total Bits |`132 bits` |`264 bits` | -|Total Words |`132/11 = 12 words` |`264/11 = 24 words` | -|----------------|-------------------------------|-----------------------------| - -In terms of actual pre-image resistance, the initial entropy should be generated in a cryptographically-secure manner that is pre-image resistant and resistant to other attacks, such as outlined in the [W3C Cryptography API](https://www.w3.org/TR/WebCryptoAPI/) or via the [secrets](https://docs.python.org/3/library/secrets.html) module in Python), and the psuedo-random binary string that results will be machine-readable where the purpose of encoding it into a mnemonic is to make it easier to notate, recite, read, and write, (i.e. human-readable) compared to binary (machine-readable). - - - -### Example of various notation methods for a given binary (base 2) string: - -- Binary (base-2) format: ->`00001001100111001011111110101111000100110000001100100111011101101011100000111110011000110100110000101100001011101010000000010111` -- Hexidecimal(base-16) format: -> `99cbfaf13032776b83e634c2c2ea017` -- Decimal (base-10) integer format: ->`12776938083042441757844264502598475799` -- Mnemonic format (BIP39): ->`another tourist type champion crash robust thought small equip gesture pool cool` (note: this mnemonic conveys 132 bits as the extra 4-bit checksum is deterministic based on the initial 128 bits). - -- >Hatnotation format: - > `9$B_,4-C$T(W_O;-)B'0N` - - -## Important - -The Hatnotation system is *not intended to be an alternative to human-readable mnemonics*, but rather a complement and simply another representation of the machine-readable code, with the benefit of a reduction in the number of characters needed to notate and backup/store the data, using common and special characters from a library of 64 total possible characters (in range of 2^6). - - - -### Security: - -Just as a mnemonic that represents a 132 bits of some initial entropy should convey 128 bits of security if generated properly, as the last 4 bits are deterministically derived from the hash-based checksum computation (hashing the initial entropy as a byte array). Those same 132 bits can be encoded using the Hatnotation system which will result in 22 characters, sourced from the 64 character library. Mathematically, 64^22 == 2^132, hence why there is no information/security loss, for example. - -### Lemma -For any arbitrary binary (base-2) string x of length n, after hatnotation is applied to x, the length n = ((x - (x % 6))/6)+(x %6, optionally in some cases depending on how the encoder/decoder is constructed). Optimal compression will occur when the x modulo 6 is equal to zero, and least optimum when x modulo 6 is equal to 5 (The assumption in this last sentence should be checked). - -Below are two examples of when notation is optimum, using 132 bits and 264 bits as an example, and which are standard bit-lengths for the underlying entropy that represents 12-word or 24-word mnemonics used with crypto wallets. - - -- `(64^((132-(132 % 6)) / 6) == 2^132` - -- `(64^((264-(264 % 6)) / 6) == 2^264` - - -| Private Key |12-word mnemonic |24-word mnemonic | -|----------------|-------------------------------|-----------------------------| -| 128 bits |21 characters |Checksum must be computed | -| 132 bits |22 characters |Checksum included | -| 256 bits |42 characters |Checksum must be computed | -| 264 bits |44 characters |Checksum included | -|----------------|-------------------------------|-----------------------------| - - -## Library - -Using the binascii libary in python which contains the string library, we source 64 characters as follows: - -10 digit values (symbols 0-9) -26 Uppercase letter values (letters A-Z) -28 Special character values (!-`) - -`Index | 6-bit number, | character/value,` --- | -- | -- -0 | "000000", | "0", -1 | "000001", | "1", -2 | "000010", | "2", -3 | "000011", | "3", -4 | "000100", | "4", -5 | "000101", | "5", -6 | "000110", | "6", -7 | "000111", | "7", -8 | "001000", | "8", -9 | "001001", | "9", -10 | "001010", | "A", -11 | "001011", | "B", -12 | "001100", | "C", -13 | "001101", | "D ", -14 | "001110", | "E", -15 | "001111", | "F", -16 | "010000", | "G", -17 | "010001", | "H", -18 | "010010", | "I", -19 | "010011", | "J", -20 | "010100", | "K", -21 | "010101", | "L", -22 | "010110", | "M", -23 | "010111", | "N", -24 | "011000", | "O", -25 | "011001", | "P", -26 | "011010", | "Q", -27 | "011011", | "R", -28 | "011100", | "S", -29 | "011101", | "T", -30 | "011110", | "U", -31 | "011111", | "V", -32 | "100000", | "W", -33 | "100001", | "X", -34 | "100010", | "Y", -35 | "100011", | "Z", -36 | "100100", | "!", -37 | "100101", | """, -38 | "100110", | "#", -39 | "100111", | "$", -40 | "101000", | "%", -41 | "101001", | "&", -42 | "101010", | "’", -43 | "101011", | "(", -44 | "101100", | ")", -45 | "101101", | "*", -46 | "101110", | "+", -47 | "101111", | ",", -48 | "110000", | "-", -49 | "110001", | ".", -50 | "110010", | "/", -51 | "110011", | ":", -52 | "110100", | ";", -53 | "110101", | "<", -54 | "110110", | "=", -55 | "110111", | ">", -56 | "111000", | "?", -57 | "111001", | "@", -58 | "111010", | "[", -59 | "111011", | "\", -60 | "111100", | "]", -61 | "111101", | "^", -62 | "111110", | "_", -63 | "111111", | "`", - -## Library verification - -In Python version 3.7 using the strings library, the following steps can be taken to verify the library and character order and by omitting the last 4 characters "{|}~" in the fourth step below (zeroed-index values 64-67 which have been omitted from the above list as well): - -- ```>>> import string``` -- ```>>> dir(string)['Formatter', 'Template', '_ChainMap', '_TemplateMetaclass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_re', '_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']``` -- ```>>> print(string.digits+string.ascii_uppercase+string.punctuation)``` -- ```0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~``` - -(i.e. ~~```"{|}~"```~~) - -## Requirements - -Python 3 or higher - - -## Installation: - -## Tests: - - - -## Reources: - -Other base64 encoding schemes: https://en.wikipedia.org/wiki/Base64 -Notational conventions: https://tools.ietf.org/html/rfc2822 - -## Roadmap/Plans: - - +This readme is on the development branch and intentionally left blank, please see the [readme.md](https://github.com/hatgit/hatnotation/blob/master/README.md)file on the master branch. From d8cef4a1e0b8a1b6d3dc8edd7a0562416be2da12 Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Tue, 16 Apr 2019 11:42:39 -0400 Subject: [PATCH 10/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 342bcd9..d579b26 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -This readme is on the development branch and intentionally left blank, please see the [readme.md](https://github.com/hatgit/hatnotation/blob/master/README.md)file on the master branch. +This readme is on the development branch and intentionally left blank, please see the [readme.md](https://github.com/hatgit/hatnotation/blob/master/README.md) file on the [master branch](https://github.com/hatgit/hatnotation/blob/master). From 1ce38ea4ed953ea2b3bb3554d9e88e3c4f1f9986 Mon Sep 17 00:00:00 2001 From: Steven Hatzakis Date: Tue, 16 Apr 2019 11:43:09 -0400 Subject: [PATCH 11/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d579b26..510612d 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -This readme is on the development branch and intentionally left blank, please see the [readme.md](https://github.com/hatgit/hatnotation/blob/master/README.md) file on the [master branch](https://github.com/hatgit/hatnotation/blob/master). +This readme is on the `development-v1` branch and intentionally left blank, please see the [readme.md](https://github.com/hatgit/hatnotation/blob/master/README.md) file on the [master branch](https://github.com/hatgit/hatnotation/blob/master). From 0ad0c18f8f6bbb50b157e8a8f29dadbf28bae752 Mon Sep 17 00:00:00 2001 From: john Date: Tue, 16 Apr 2019 12:22:54 -0400 Subject: [PATCH 12/20] decodeFunction.py --- decodeFunction.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 decodeFunction.py diff --git a/decodeFunction.py b/decodeFunction.py new file mode 100644 index 0000000..bc9ce73 --- /dev/null +++ b/decodeFunction.py @@ -0,0 +1,84 @@ +import string +import binascii +import math +import secrets +b64dict=dict() + +base64library=["0", +"1", +"2", +"3", +"4", +"5", +"6", +"7", +"8", +"9", +"A", +"B", +"C", +"D", +"E", +"F", +"G", +"H", +"I", +"J", +"K", +"L", +"M", +"N", +"O", +"P", +"Q", +"R", +"S", +"T", +"U", +"V", +"W", +"X", +"Y", +"Z", +"!", +'"', +"#", +"$", +"%", +"&", +"'", +"(", +")", +"*", +"+", +",", +"-", +".", +"/", +":", +";", +"<", +"=", +">", +"?", +"@", +"[", +"\\", +"]", +"^", +"_", +"`"] +for i in range(len(base64library)): + b64dict[base64library[i]]=i + +def decodeAsBin(string): + output=[] + print(len(string)) + for j in range(len(string)): + + if(string[j]!=' '): + output.append(bin(b64dict[string[j].upper()])[2:].zfill(6)) + + return output + +print(decodeAsBin('hello world')) From 6d5a242b7a948c3e903e5a894ca174ba2df9cb02 Mon Sep 17 00:00:00 2001 From: john Date: Tue, 16 Apr 2019 23:18:46 -0400 Subject: [PATCH 13/20] added decode function in to base64decode.py --- .idea/hatnotation.iml | 11 +++ .idea/misc.xml | 4 + .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 ++ .idea/workspace.xml | 169 ++++++++++++++++++++++++++++++++++++++++++ base64decode.py | 97 ++++++------------------ decodeFunction.py | 84 --------------------- 7 files changed, 221 insertions(+), 158 deletions(-) create mode 100644 .idea/hatnotation.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml delete mode 100644 decodeFunction.py diff --git a/.idea/hatnotation.iml b/.idea/hatnotation.iml new file mode 100644 index 0000000..6711606 --- /dev/null +++ b/.idea/hatnotation.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..65531ca --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..44f6d3b --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..0236722 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +