По хорошо известным причинам основные почтовые ящики и чат-приложения в Китае будут отслеживать информацию, которую вы получаете и отправляете. Если вам нужно передать какой-то совершенно секретный контент, очевидно, вам нужно зашифровать свой контент.
Но как рассказать другим о зашифрованных паролях? Вы звоните? Если это общение один на один, этот метод действительно не проблема.
Но если сейчас это одностороннее соединение, вам будут писать несколько человек. Вы хотите, чтобы все, кто связывается с вами, шифровали информацию перед ее отправкой вам, и только вы могли ее расшифровать? Если используется только один пароль, то сообщение, которое посылает вам A, может быть просмотрено B. Вам нужно установить уникальный пароль для всех?
Чтобы решить эту проблему, мы можем использовать асимметричное шифрование. Ключ шифрования асимметричного шифрования и ключ дешифрования являются отдельными. Ключи шифрования можно сделать общедоступными и видимыми для всех. Каждый может отправлять вам зашифрованные сообщения, используя один и тот же ключ шифрования. Но только ключ дешифрования в ваших руках может расшифровать зашифрованный текст.
Алгоритм RSA — это алгоритм асимметричного шифрования.
Этот алгоритм очень надежен, и чем длиннее ключ, тем сложнее его взломать. Согласно опубликованной литературе, самый длинный ключ RSA, который был взломан до сих пор, составляет 768 двоичных битов. То есть ключи длиннее 768 бит не могут быть взломаны (по крайней мере, публично об этом никто не заявлял). Следовательно, можно считать, что 1024-битный ключ RSA в основном безопасен, а 2048-битный ключ чрезвычайно безопасен. ——«Принцип алгоритма RSA (1)»
Ключ шифрования в алгоритме RSA называется открытым ключом, а ключ дешифрования — закрытым ключом. Вам просто нужно сохранить закрытый ключ в безопасности. Открытый ключ можно разместить в блоге, и любой, кто хочет отправить вам сообщение, просто должен зашифровать сообщение с помощью открытого ключа и отправить его вам.
Как мы используем алгоритм RSA для шифрования и дешифрования в Python? Вы можете установить стороннюю библиотеку под названиемrsa:
pip install rsa
После завершения установки пробуем зашифровать кусочек китайщины:今晚8点老地方碰头.
Первый шаг — создать открытый и закрытый ключи.
import rsa
public_key, private_key = rsa.newkeys(1024)
Давайте теперь напечатаем эти два ключа, как показано на изображении ниже:
Число 1024 в нем означает генерацию 1024-битного ключа. Вы также можете написать 2048 или 4096..., если это так.И n>4 достаточно. Чем больше битов, тем надежнее, но медленнее шифрование и дешифрование.
Сгенерированный ключ представляет собой объект Python, который неудобно отправлять другим. Таким образом, мы можем преобразовать их вpemФормат:
public_key_str = public_key.save_pkcs1()
private_key_str = private_key.save_pkcs1()
Как показано ниже:
Теперь у нас есть две строки. Это открытый и закрытый ключ в формате pem, открытый ключ начинается сBEGIN RSA PUBLIC KEYначало, короче; приватные ключи начинаются сBEGIN RSA PRIVATE KEYНачало, дольше.
Среди них закрытый ключ следует хранить у себя и не допускать утечки. Вы можете отправить открытый ключ другим пользователям с помощью любых средств связи, таких как QQ, WeChat, электронная почта, SMS и т. д.
Ключ необходимо сгенерировать только один раз, и приведенный выше код не нужно выполнять в будущем.
Теперь, когда у нас есть открытый и закрытый ключи, мы можем начать отправлять сообщения.
Обратите внимание, что в следующем коде используются открытый и закрытый ключи в формате pem.
Сначала мы шифруем информацию с помощью открытого ключа.
public_key_str = '''
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAIWmLWCvb3kSJ7+ys9JZ/rqqgIcYwf9bcEl9/BQd4XnsSHHoyAyG+bPI
1YRGaAnmKLGeEcgrJE1sQIqIMdeHLHVTWUNh4Wr8o+1fyTrlpK0fCNmLb3qRabsg
wRxoSEflXAchBLlHWQoHkaMjcfR7zTFe5I/ogx5gtSX0TQCSmLANAgMBAAE=
-----END RSA PUBLIC KEY-----
'''
msg = '今晚8点老地方碰头'
public_key = rsa.PublicKey.load_pkcs1(public_key_str.encode())
encryptd_msg = rsa.encrypt(msg.encode(), public_key)
После шифрования мы получаем данные типа bytes, как показано на следующем рисунке:
Обратите внимание, что данные в байтах здесь не могут быть.decode()в строку. Так как же его отправить другим?
В это время вы можете поместить слой кодировки base64 на его внешний слой, чтобы превратить его в строку:
import base64
encryptd_msg_str = base64.b64encode(encryptd_msg).decode()
Как показано ниже:
Теперь вы можете поместить зашифрованный текст
RzwfgCFUhLKYiXM7frOcBL7VyLIh1M7pJ8Gpaz9j7HksjYqsw8DzreFziBNi/S0GGciIfWsvr5pUvYFA7wacOjHqluZ7KVx1oEOdg/x6wyeb1UdQ9cR6PzMlgpidpzUknhsGIAmxjtt6EUL+tJVUbzfXHgs5wETxFZQtRHLcKag=
Отправьте его другим через любой общедоступный канал. Это зашифрованный текст.
Как человек, у которого есть закрытый ключ, расшифровывает зашифрованный текст после его получения? Тоже очень просто:
import rsa
import base64
encryptd_msg_str = '''
RzwfgCFUhLKYiXM7frOcBL7VyLIh1M7pJ8Gpaz9j7HksjYqsw8DzreFziBNi/S0GGciIfWsvr5pUvYFA7wacOjHqluZ7KVx1oEOdg/x6wyeb1UdQ9cR6PzMlgpidpzUknhsGIAmxjtt6EUL+tJVUbzfXHgs5wETxFZQtRHLcKag=
'''
private_key_str = '''
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQCFpi1gr295Eie/srPSWf66qoCHGMH/W3BJffwUHeF57Ehx6MgM
hvmzyNWERmgJ5iixnhHIKyRNbECKiDHXhyx1U1lDYeFq/KPtX8k65aStHwjZi296
kWm7IMEcaEhH5VwHIQS5R1kKB5GjI3H0e80xXuSP6IMeYLUl9E0AkpiwDQIDAQAB
AoGAYNu2N0PtfcjylbNlLyWZvp6i10XSEsap8hkj/1BIgJwFRMh3cty/StRaKar8
62+qPk9Yg8EAZjv16nAZjRcVQ031/F57FGR3JdZ43fuT/no0gV+mEIc72ypNuhUl
M9iccyhEq0xX4eixex3nUALBcPY17ElhvaD8cDZoW2QGFAECRQCHR4RHmgOzoyuM
Wnov7/WetV8Eqxy1/XQOkvSTWEv6Gyc1vlc/xsRGLwXiUt0BFoOnMRCOAQJwjxSn
EbbRzey3YdzX4QI9APzqPCqiEZ4eNnh8F7eOmQYSRurx2b5eyEg3zrVgJHCNOE1i
8uidT4mLBx4nfIwV8/ttw7TjzvhQtnBtrQJEaAzyCcDEqB8RF9tfsA95dKE8fHLA
mppf8fXGeK6pga3w8r18jmlr/i+c7v+dTYDrsmVivla4casbz4UogSdKs6JqIwEC
PGkUdO0Nqx4z1VPX0w7Lq15vZ5Gj7GEBBlui/Do1eM5ejj7w1pW5DlvKLKnlpASb
9mPHZiGY6NwYxMQPfQJEGg5vG+TN7G4PxbCzeInxxIScpmDE8TBPixrIy9qM/cjb
Excc1vCiR8+Kbhr/RhYveaGuKIKaXrVBhzQJZDYd8298mmA=
-----END RSA PRIVATE KEY-----
'''
private_key = rsa.PrivateKey.load_pkcs1(private_key_str.encode())
encryptd_msg = base64.b64decode(encryptd_msg_str.encode())
msg = rsa.decrypt(encryptd_msg, private_key).decode()
print(msg)
Эффект операции показан на следующем рисунке:
Шифрование RSA имеет ограничение на длину зашифрованного (незашифрованного текста). Поскольку в окончательном зашифрованном тексте будет 11 байт содержимого для хранения метаинформации, связанной с шифрованием, для 1024-битного ключа длина открытого текста, который может быть зашифрован, составляетбайт.
Что если вычислить длину строки в байтах? Вы можете использовать следующий код:
msg = '今晚8点老地方碰头'
print(len(msg.encode()))
Эффект операции показан на следующем рисунке:
Объясните, что длина этих 8 китайских иероглифов плюс 1 цифра составляет 25 байт (поскольку в Python китайский иероглиф занимает 3 байта, числа и буквы занимают 1 байт,)
Если вы хотите отправить длинную строку, вам нужно сначала преобразовать строку в данные байтов, затем разделить ее на множество групп в соответствии с группой из 117 байтов и зашифровать каждую группу отдельно. При расшифровке с密钥位数/8bytesГруппа сначала разбивает зашифрованный текст, затем расшифровывает один за другим и, наконец, расшифровывает байты данных открытого текста..decode()Преобразовать в строку.
Давайте сначала реализуем код шифрования:
def encrypt(msg, public_key):
msg_bytes = msg.encode()
encryptd_msg = b''
chunk_size = len(msg_bytes) // 117 + 1
for chunk_index in range(chunk_size + 1):
chunk = msg_bytes[chunk_index * 117: (chunk_index + 1) * 117]
encryptd_msg += rsa.encrypt(chunk, public_key)
encryptd_msg_str = base64.b64encode(encryptd_msg).decode()
return encryptd_msg_str
В этом коде мы сначала преобразуем открытый текст в данные байтового типа, а затем нарезаем. Здесь можно вырезать три байта, соответствующие китайцу. Но это мало влияет. Зашифруйте 117 байт в виде блока открытого текста. Объедините данные зашифрованных байтов в длинную строку, а затем используйте Base64 для кодирования в целом. Наконец, отправьте зашифрованный текст, созданный путем кодирования, другим. Как показано ниже:
Зашифрованный текст, который мы здесь генерируем:
K2Tb9tDQPXBiuCBuWxOR9zBTbDSN2WaF+n+P2RUA9CHdIKvIHvqfMZ60xTsJ7UqZlB4ykzu/ccsTEmp8vqiVaJSSwg5TgDYLdPmk5/6leZaBW4BqyJ2g0PcyCcUvhjxc7P4AIC6MKYZ+74qTgm+Pf8qnY/riOeEZUuxoq0KaFZQOpvGpwnAgpCad8a6MJ7TbyZpepkZr+GbFDdbmegrA6HN9zCIw30c4g0RCiD01PwerUtbK9YXr/aO8hrFEim8bWDos3bpNrQtk8ST4fM9OczXKEoTSuv+f+Ue2s1YFJ00tAyD4GF8QeZ5mUc2ydNyovkvEfhwhy1eOcI/HQQZn2DPxLb3gB4tgE/Hoo4Xblj8ZWpeMe5BrAdT4Dk1qduOJ/A3RnfvhEbojwx30pEU+JipW4AqCPxK26Q+WsYyqVCBM29vWWgxttthxBidpM0GYII1OIfZvWG8GAAMPvotTwrdGOF/Nk355qLlwiHJhsjz0uN0p9PjyUY+xHobDrmuggBHejM69PwelnG5ubxjhBoqKtbBttU4IWfDZq+d3LZdhwZMp2PsXkSzu+IIgpAn0+F/5bZkRAv8XTAv1YFnYLwJI9vyXfMIyoo4wcqDpNmJrMoaW0hvpJ8jMPna0lI9/Up2JO8GRhq+C+pgeM37OUE70UGrqw1R25yO8Y60of69HqfdFgLalhD7egJ42gRt9Lman7dsokWrpySp6Tq7jFJ/h/OL2Kma8Tqeodd1B0/bINNBkK2hb5EIq7cu6xEd5LevieYllEw0LNK03aWERMfkIuOSabzDfn1kedZnK4PlZ+DiXaoe8uUlAlfZsWNBNV94C3+Ji/a1jYk+ZEUZMxA==
Далее напишем программу расшифровки:
def decrypt(encryptd_msg_str, private_key):
encryptd_msg = base64.b64decode(encryptd_msg_str.encode())
chunk_size = len(encryptd_msg) // 128
msg_bytes = b''
for chunk_index in range(chunk_size):
chunk = encryptd_msg[chunk_index * 128: (chunk_index + 1) * 128]
msg_bytes += rsa.decrypt(chunk, private_key)
return msg_bytes.decode()
В программе расшифровки мы сначала декодируем строку в кодировке Base64 в данные байтового типа, а затем разбиваем их на группы по 128 байт. Расшифруйте каждую группу отдельно. Затем объединение байтов данных, сгенерированных каждым расшифровыванием. Наконец, используйте объединенные данные.decode()Преобразовать в строку.
В частности, следует отметить, что для каждого блока шифртекста после завершения расшифровки его нельзя напрямую.decode(). Поскольку в конце может быть только половина китайского языка, прямое преобразование строки приведет к сообщению об ошибке.Необходимо объединить все расшифрованные байты данных перед преобразованием их в строку. Дополнительные вопросы о срезах данных байтового типа см. в моей предыдущей общедоступной учетной записи:Один навык в день: повторяющиеся функции Python Bytes Dataодна статья.
Результат работы программы расшифровки показан на следующем рисунке:
Обратите внимание, что если ваш ключ 2048-битный, то открытый текст будет разделен на группы по 245 байт, а затем зашифрован во время шифрования; при расшифровке зашифрованный текст будет разделен на группы по 256 байт, а затем расшифрован.
Наконец, если у вас есть какая-либо информация, которую вы не хотите, чтобы ее увидели известные организации, и хотите отправить мне, вы можете использовать следующий открытый ключ для шифрования информации, а затем отправить мне зашифрованный текст:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEApQSWvu/C5NH3aEGMqFTeiJrXbOM2Qi+uXc+FiApEWDYdyEMPQWKH
exJiFoyAa+JJ8OfmkTIVktkx0VqEcvfjfKxrGPk9JuQ6WL4/UUYs8/F+2ArDnMyR
lWcqaf1658QjrWYbFHxQ0eEOZ6RcRKME3p431mDMqeDpQtqlDyeMKGp7hSv5gnpd
Qjlyl1Jgoa4lAzyPv66IM1PD207qjLFCTY0udiWSFDiUlvgXcBHDypUqWGOUUSLE
vVXIE+KYNbR2g23iRa1IJGSCEz1xllt7QpygCwwd+vVGD8zaCHOEE7Fex0K/ybhi
Nvdt19qgxE8aIwGt0ln71DNpn+yZsq4fIwIDAQAB
-----END RSA PUBLIC KEY-----
Ключ 2048 бит.