Ubuntu + Python + OpenSSL 生成并保存文件哈希值

在Ubuntu中生成文件哈希值的方法有几种,包含命令行和Python的hashlib接口调用。命令行生成文件哈希值有两种方式:
1)md5sum / shasum / sha1sum / sha224sum / sha256sum / sha384sum / sha512sum等命令
2)openssl命令,支持的哈希值生成方法包含:

Message Digest commands (see the `dgst’ command for more details)
blake2b512 blake2s256 md4 md5
rmd160 sha1 sha224 sha256
sha3-224 sha3-256 sha3-384 sha3-512
sha384 sha512 sha512-224 sha512-256
shake128 shake256 sm3

而hashlib接口调用在另一文中有简要描述。这里实现的方法是通过调用系统命令openssl实现的,即openssl md5 filename的实现格式。
用法:python3 genhash.py -ffilename -mmd5 或者 python3 genhash.py --file filename --method md5。测试操作系统为Ubuntu24.04。
genhash.py

'''
File: genhash.py
Author: Nega
Created: 12/02/24 Mon.
Updated: 12/03/24 Tue.
'''
#!/bin/python3

import optparse
import os
import sys

# 声明支持的哈希方法,OpenSSL支持不仅包含以下声明的方法,以下声明仅为演示
SUPPORTED_HASH_METHODS = ('md2/md4/md5/sha1/sha224/sha256/sha384/sha512/sha3-224/sha3-256/sha3-384/sha3-512/blake2s256/blake2b512/',)

def __generate_hash__(file_name, gen_method='md5', debug=False):
    if gen_method is None or type(gen_method) != type('') or (gen_method + '/') not in SUPPORTED_HASH_METHODS[0]:
        print('[\033[1;31mFAIL\033[0;39m] ' + str(gen_method) + ' not string or not supported')
        return
    if file_name is None or type(file_name) != type('') or file_name.strip() == '':
        print('[\033[1;31mFAIL\033[0;39m] ' + str(file_name) + ' not string or invalid name')
        return
    if not os.path.exists(file_name) or not os.path.isfile(file_name):
        print('[\033[1;31mFAIL\033[0;39m] ' + file_name + ' \033[1;31mnot existed\033[0;39m file')
        return
    res = os.popen('openssl ' + gen_method + ' ' + file_name)
    digest_raw = res.read()
    if debug is True:
        print(digest_raw)
    digest_str = digest_raw.split('=')[1].strip()
    print('[' + gen_method.upper() + '] ' + digest_str)
    
    temp = file_name
    root_dir = None
    if temp.startswith('~'):
        temp = temp.replace('~', '/home/' + os.popen('whoami').read().replace('\n', ''))
        root_dir = temp
    elif temp.startswith('./'):
        temp = os.getcwd() + temp[1:]
        root_dir = temp
    else:
        root_dir = os.path.abspath(temp)
    if root_dir is None:
        print('[ERR] root directory not existed')
        return
    # print('[SOURCE]' + root_dir)
    
    dig_file = '.' + gen_method
    hash_dir = '__hash_cache__'
    file_dir = root_dir[:root_dir.rindex('/')] + '/' + hash_dir
    sim_file_name = root_dir[root_dir.rindex('/'):]
    if not os.path.exists(file_dir) or not os.path.isdir(file_dir):
        os.makedirs(file_dir)
    file = file_dir + sim_file_name + dig_file
    # print('[DEST] ' + file)
    if os.path.exists(file) and os.path.isfile(file):
        print('[\033[1;33mOVERRIDE\033[0;39m] digest file existed, rewriting..')
        res2 = os.popen('chmod +w ' + file)
        rstr = res2.read()
        if rstr != '':
            print('[FAIL] not writable')
            return
    with open(file, 'w') as f:
        f.write(digest_str)
        f.flush()
        f.close()
    if os.path.exists(file):
        res2 = os.popen('chmod 664 ' + file)
        rstr = res2.read()
        if rstr == '': print('[\033[1;32mPASS\033[0;39m] TEST')
        res3 = os.popen('ls -al | grep ' + file_name)
        rstr2 = res3.read()
        if rstr2.strip() != '': print(rstr2.replace('\n', ''))
    else:
        print('\033[1;31m[TEST]\033[0;39m Digest file generation failed')
        
def __pre_generate__(args=None):
    if args is None or type(args) != type([]):
        print('[TEST] Aborted with invalid arguments')
        return
    _parser = optparse.OptionParser()
    _parser.add_option('-f', '--file',
                       type='string',
                       dest='gen_file',
                       default=None,
                       help='Choose a file to generate it\'s hash')
    _parser.add_option('-m', '--method',
                       type='string',
                       dest='hash_method',
                       default=None,
                       help='Specify a hash method, such as md2/md3/md4/md5/sha1/sha224/sha256/sha384/sha512/blake2s256/blake2b512')
    (_options, _) = _parser.parse_args(args)
    gen_file = None
    if _options.gen_file:
        gen_file = _options.gen_file
    gen_method = None
    if _options.hash_method:
        gen_method = _options.hash_method.lower()
    __generate_hash__(gen_file, gen_method, False)
        
if __name__ == '__main__':
    try:
        __pre_generate__(sys.argv)
    except Exception as err:
        print('\033[1;31mERR.\033[0,39m ' + str(err))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值