Хеширование файла csv в python с ключом

У меня есть CSV-файл с более чем 1000 адресов электронной почты, которые я хочу хэшировать с помощью SHA256 HMAC и общего ключа, закодированного в Base64.

Была аналогичная проблема здесь, но я не могу адаптировать решение к работай на меня. Я новичок в Python и не знаю, где изменить код, чтобы использовать общий ключ.

Это немного адаптированный код из ответа:

import csv
import hashlib
import hmac
import base64

IN_PATH = 'test.csv'
OUT_PATH = 'test_hashed.csv'
ENCODING = 'utf8'
HASH_COLUMNS = dict(Mail='md5')


def main():
    with open(IN_PATH, 'rt', encoding=ENCODING, newline='') as in_file, \
            open(OUT_PATH, 'wt', encoding=ENCODING, newline='') as out_file:
        reader = csv.DictReader(in_file)
        writer = csv.DictWriter(out_file, reader.fieldnames)
        writer.writeheader()
        for row in reader:
            for column, method in HASH_COLUMNS.items():
                data = row[column].encode(ENCODING)
                digest = hashlib.new(method, data).hexdigest()
                row[column] = '0x' + digest.upper()
            writer.writerow(row)

if __name__ == '__main__':
    main()

Входной файл (.csv) выглядит следующим образом:

Mail
[email protected]
DJÖ[email protected]
JSNÖ[email protected]
[email protected]
[email protected]

И с приведенным выше кодом выходной файл выглядит так:

0xB6A77B6EB853CC4CC8342B312293FA9C
0xEB439592D8EEC2A38A597350EF80E512
0x833EB6AEC1D03D7D8C94606E0D749B80
0x8007D8D1702E8A749EBD6033A52A7897
0x415E067487C4A5FBDB86AB0F855DB114

Но поскольку я хочу использовать HMAC с секретным ключом и sha256, приведенное выше решение мне не подходит, и я не знаю, как внедрить этот подход.

Ключ будет примерно таким:

123Abc

Я пытался сделать что-то подобное, но для всего файла:

import hmac
import hashlib
import base64

secret = "123Abc"
secret_bytes = bytes(secret, 'latin-1')
data = "[email protected]"
data_bytes = bytes(data, 'latin-1')

digest = hmac.new(secret_bytes, msg=data_bytes, digestmod=hashlib.sha256).digest()
signature = base64.b64encode(digest).decode()

Таким образом, мой вопрос заключается в том, как я могу включить хеширование HMAC SHA 256, используя секретный ключ, в приведенном выше коде? Я просто не могу понять, какие параметры изменить?


person ChinChix    schedule 28.02.2018    source источник
comment
Итак, как можно использовать «общий ключ»? Используется ли он в качестве префикса к адресу электронной почты? Вы уже просмотрели hashlib документацию по модулю?   -  person Martijn Pieters    schedule 28.02.2018
comment
Здесь нам нужно больше деталей: предоставьте образец входных данных, ожидаемый результат и то, что вместо этого происходит в настоящее время.   -  person Martijn Pieters    schedule 28.02.2018
comment
@MartijnPieters Я надеюсь, что редактирование поможет прояснить мою проблему, а также мои текущие попытки. Спасибо   -  person ChinChix    schedule 28.02.2018
comment
Рад, что вы обновились, потому что HMAC отличается от хэша SHA256. Он использует хэш, но вы можете просто хэшировать, и вы получите результат, отличный от того, который HMAC выдаст с тем же хэшем.   -  person Martijn Pieters    schedule 28.02.2018


Ответы (1)


Я не думаю, что вам нужно возиться со словарем; здесь у вас нет переменного количества столбцов, вы применяете преобразование только к одному столбцу.

Будет легче следовать, если вы просто поместите свой рабочий метод HMAC в функцию:

import hmac
import hashlib
import base64

secret = "123Abc"
secret_bytes = bytes(secret, 'latin-1')

def create_signature(email, secret_bytes):
    data_bytes = email.encode('latin-1')
    digest = hmac.new(secret_bytes, msg=data_bytes, digestmod=hashlib.sha256).digest()
    signature = base64.b64encode(digest).decode()
    return signature

Теперь это аккуратно создает строку Base64 с дайджестом HMAC из адреса электронной почты и вашим (закодированным) секретом:

>>> create_signature('[email protected]', secret_bytes)
'3KaSw4QeA5l0rz49uutaDGemn4Et4CQnbnngm6mmpjE='

Теперь вы можете применить это к значениям столбца 'Mail' и записать новый CSV с результатами:

with open(IN_PATH, 'rt', encoding=ENCODING, newline='') as in_file, \
        open(OUT_PATH, 'wt', encoding=ENCODING, newline='') as out_file:
    reader = csv.DictReader(in_file)
    writer = csv.DictWriter(out_file, reader.fieldnames)
    writer.writeheader()
    for row in reader:
        row['Mail'] = create_signature(row['Mail'], secret_bytes)
        writer.writerow(row)

Демо:

>>> import sys, csv, io
>>> demo_input = io.StringIO('''\
... Mail
... [email protected]
... DJÖ[email protected]
... JSNÖ[email protected]
... [email protected]
... [email protected]
... ''')
>>> demo_output = io.StringIO()
>>> with demo_input as in_file:
...     reader = csv.DictReader(in_file)
...     writer = csv.DictWriter(demo_output, reader.fieldnames)
...     writer.writeheader()
...     for row in reader:
...         row['Mail'] = create_signature(row['Mail'], secret_bytes)
...         writer.writerow(row)
...
46
46
46
46
46
>>> print(demo_output.getvalue())
Mail
3KaSw4QeA5l0rz49uutaDGemn4Et4CQnbnngm6mmpjE=
dP9IU66yKnYP/6mFRZ6TAAAN3lmxAcUPk9o1iFfpGDs=
ajNdCZF8ndw2SrgtSzcVCbeSpFsXI/Z6Ep0IC2fj+WU=
TgeFEj8CgvcQbVcLHTIIY1ULLnYkWAZaia5k01IQiJY=
Xu94abwV/5/HUXY+T3NpUgulGvew+L0UYzkPuRSv/98=
person Martijn Pieters    schedule 28.02.2018
comment
Спасибо большое за помощь! Это отлично работает! - person ChinChix; 28.02.2018