preface
Tip: the test run environment is Python 3.7.5 and the IDE is Pycharm2020.1. The article contains three questions: 1. Calculating hash value and message authentication; 2. Avalanche effect of hash function; 3. Brute force MD5. Copying the past source code may need to change the output format.
1, Calculate hash value and message authentication
Title Description: write a program that can calculate text MD5, SHA512 and hmac.
1. Import and storage
The code is as follows:
import hashlib import hmac from hashlib import md5, sha256, sha512
See the official documentation for the use of the Library:
hmac -- key based message authentication
hashlib - secure hash and message digest
2. Realization
Implementation – version 1:
# It was written at the beginning for the experimental version import hashlib import hmac from hashlib import md5, sha256, sha512 def myhash(str): res = hashlib.md5(str.encode(encoding="utf-8")) print(res.hexdigest()) def myhmac(key, str, mode): # param key: the key used to calculate the message verification code # param str: string to calculate the message verification code # param mode: hash function used key = key.encode(encoding="utf-8") str = str.encode(encoding="utf-8") if mode == 'md5': my_hmac = hmac.new(key, str, digestmod=md5) res1 = sha512(str) print(res1.hexdigest()) print(my_hmac.hexdigest()) elif mode == 'sha256': res1 = sha512(str) print(res1.hexdigest()) my_hmac = hmac.new(key, str, digestmod=sha256) print(my_hmac.hexdigest()) elif mode == 'sha512': res1 = sha512(str) print(res1.hexdigest()) my_hmac = hmac.new(key, str, digestmod=sha512) print(my_hmac.hexdigest()) if __name__ == "__main__": str = input() key = input() mode = input() myhash(str) myhmac(key, str, mode)
In order to carry out the experiment, I wrote it smelly and long, unsightly and difficult to read, that is, to realize a function, so I went to refer to the code of BossXie. After reading it, I knew it was 666, which was not as concise as words, so I also wrote an improved version roughly according to my ideas:
# Improved version import hashlib import hmac from hashlib import md5, sha256, sha512 def myhash(str): res = hashlib.md5(str.encode(encoding="utf-8")) print("md5: " + res.hexdigest()) def myhmac(key, str, mode): # param key: the key used to calculate the message verification code # param str: string to calculate the message verification code # param mode: hash function used key = key.encode(encoding="utf-8") str = str.encode(encoding="utf-8") my_hmac = hmac.new(key, str, mode) res1 = sha512(str) print("sha512 " + res1.hexdigest()) print("hmac: " + my_hmac.hexdigest()) if __name__ == "__main__": str = input() key = input() mode = input() myhash(str) myhmac(key, str, mode)
Test the results:
It's really much more comfortable~
2, Avalanche effect of hash function
Title Description: write a program that can verify the avalanche effect of hash function MD5.
(secretly Tucao: this question should be the most annoying thing in this experiment. Although it is not difficult to write after finishing, there are really few hints on the title. There are not many materials to make complaints about, but it is difficult to write, and of course it is probably my dish.)
realization
The code is as follows:
import hashlib def encode(s): return ' '.join([bin(ord(c)).replace('0b', '') for c in s]) def decode(s): return ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]]) # This function is used to calculate the number of different bits of two strings def cmpcount(str1, str2): count = 0 for i in range(0, len(str1)): times += 1 if str1[i] != str2[i]: count += 1 return count def avalanche(str, nbyte, mbit): # param str: string to calculate hash value # Param nbyte: the number of bytes of str (from low bit to high bit) # Parem Mbit: bit number of nbyte (from low bit to high bit) h1 = hashlib.md5(str.encode(encoding="utf-8")) # Get MD5 of the original string h1 = h1.hexdigest() nbyte_place = len(str) - nbyte # Gets the location of the target byte nbytes = str[nbyte_place] # Get target byte nbyte_str = encode(nbytes) # Convert target byte to binary mbit_place = len(nbyte_str) - mbit # Get the target bit location and debug the error point for the first time mbits = nbyte_str[mbit_place] # Get target bit # bit flip + byte binary restore if mbits == '0': nbyte_str = nbyte_str[:mbit_place] + '1' + nbyte_str[mbit_place+1:] elif mbits == '1': nbyte_str = nbyte_str[:mbit_place] + '0' + nbyte_str[mbit_place+1:] nbyte_str = decode(nbyte_str) # Get modified bytes str1 = str[:nbyte_place] + nbyte_str + str[nbyte_place+1:] # Gets the modified string print("str1: " + str1) h2 = hashlib.md5(str1.encode(encoding="utf-8")) h2 = h2.hexdigest() h1 = bin(int(h1, 16))[2:] h2 = bin(int(h2, 16))[2:] if len(h1) != 128: h1 = h1.zfill(128) else: pass if len(h2) != 128: h2 = h2.zfill(128) else: pass print("h1: " + h1) print("h2: " + h2) cout_different = cmpcount(h1, h2) print(cout_different) # Test: python 2 1 if __name__ == "__main__": str, nbyte, mbit = input().split() nbyte = int(nbyte) mbit = int(mbit) avalanche(str, nbyte, mbit)
This question uses less library than the first question, so the reference library link is omitted. Let's talk about the precautions of this question:
1. The bytes are arranged from the lower bits. For example, the first byte in 'python' is' n ', the second byte is' o', and the bit bits are arranged in this way.
2. If the length of md5 encrypted binary string is less than 128 bits, you need to use zfill function to supplement. The use method is str.zfill(lenth), lenth is the number of bits to be filled in, and 128 bits are required for this problem, that is, str.zfill(128).
3. The conversion between binary and string refers to the code of a blogger, which is very nice! It looks very concise and moved to this program.
Others are basically written in the notes. If you don't understand, welcome to the comment area for discussion~
3, Brute force MD5
Title Description: write a program that can crack md5
I think the description is very concise. Let me add a little. Enter a string, md5 encrypt the string, and then compare the ciphertext through the full arrangement of letters, numbers and characters, and finally get the string before encryption. That's almost what it means.
1. Import and storage
The code is as follows:
from hashlib import md5 from string import ascii_letters, digits, punctuation # Use the string module to get letters, numbers, and characters from itertools import permutations # For Full Permutation
In fact, the usage is very simple. You'll see the code later. Comments are also written, so I won't go into details
2. Realization
The code is as follows:
# Avalanche effect of hash function # author:marxycj # date:2021-10-29 from hashlib import md5 from string import ascii_letters, digits, punctuation # Use the string module to get letters, numbers, and characters from itertools import permutations # For Full Permutation def brute_md5(md5_value): if len(md5_value) != 32: print("Not valid md5 value") return else: allkind = ascii_letters + digits + punctuation for i in range(5, 10): for j in permutations(allkind, i): md5_test = ''.join(j) md5_testmd5 = md5(md5_test.encode(encoding="utf-8")) md5_testhex = md5_testmd5.hexdigest() if md5_testhex == md5_value: print(md5_test) return if __name__ == '__main__': md5_value = input() brute_md5(md5_value)
Explain that allkind is a combination of letters, numbers and characters. Add up the three types, md5_test is used to receive full array strings and then conduct md5 brute force cracking test, perhaps called md5_try is more appropriate. There's nothing else to pay attention to~
summary
Summary:
You may not write the code quickly when you write it, and it's not as good as others. You can write it neatly, but you'd better write it yourself. After all, it's your own idea. After writing, you can modify it according to the boss. In this way, you may better improve your code ability. If you copy the code without thinking, you can learn more limited things. I'm willing to be down-to-earth, free from arrogance and impetuosity.