いくつかの一般的な暗号化アルゴリズムとPythonの実装

1はじめに

私たちが話している暗号化方法はすべてバイナリエンコード形式で暗号化されており、Pythonに対応しており、それは私たちのものBytesです。

したがって、Pythonで暗号化操作を実行するときは、操作していることを確認する必要Bytesがあります。そうしないと、エラーが報告されます。

sumメソッドBytesは、文字列と相互の変換に使用できます次のように:encode()decode()

# 方法中不传参数则是以默认的utf-8编码进行转换
In [1]: '南北'.encode()
Out[1]: b'\xe5\x8d\x97\xe5\x8c\x97'

In [2]: b'\xe5\x8d\x97\xe5\x8c\x97'.decode()
Out[2]: '南北'

注:2桁の16進数は、バイナリバイトを表示するためによく使用されます。

このbinasciiモジュールを使用すると、16進数で表示されるバイトを、暗号化と復号化でより一般的に使用される表示方法に変換できます。

In [1]: import binascii

In [2]: '南北'.encode()
Out[2]: b'\xe5\x8d\x97\xe5\x8c\x97'

In [3]: binascii.b2a_hex('南北'.encode())
Out[3]: b'e58d97e58c97'

In [4]: binascii.a2b_hex(b'e58d97e58c97')
Out[4]: b'\xe5\x8d\x97\xe5\x8c\x97'

In [5]: binascii.a2b_hex(b'e58d97e58c97').decode()
Out[5]: '南北'

2.URLエンコード

通常のURLには、ASCII文字、つまり文字、数字、および一部の記号のみを含めることができます。URLエンコードは、URL内の特殊文字(漢字など)を回避するためにブラウザーで使用されるエンコード方法です。

実際、ASCII範囲を超える文字をバンド付きの%16進形式に変換することです

In [1]: from urllib import parse

# quote()方法会自动将str转换成bytes,所以这里传入str和bytes都可以
In [2]: parse.quote('南北')
Out[2]: '%E5%8D%97%E5%8C%97'

In [3]: parse.unquote('%E5%8D%97%E5%8C%97')
Out[3]: '南北'

3.Base64エンコーディング

Base64は、64文字を使用して任意のバイナリデータを表すメソッドです。

Base64エンコーディングは、暗号化の基礎と言えます。任意のバイナリデータをBase64でエンコードできます。すべてのデータは、65文字で表現できるテキストファイルとしてエンコードできます。(65文字:A〜Z a〜z 0〜9 + / =)エンコードされたデータ〜=エンコード前のデータの4/3、これは約1/3大きくなります。

3.1。原則

image.png

  1. すべての文字をASCIIコードに変換します。
  2. ASCIIコードを8ビットのバイナリに変換します。
  3. 3つの2進数を1つのグループ(3ビット未満が後ろに0で追加されます)、合計24ビットにグループ化し、次にそれらを4つのグループに分割します。各グループは6ビットです。
  4. 6ビットバイナリの前に2つの0を追加して、8ビットを構成します。
  5. 0で埋められた2進数を10進数に変換します。
  6. Base64コードテーブルから10進法に対応するBase64コードを取得します。

3.2。説明

  1. 変換するときは、3バイトのデータを次々と24ビットバッファに入れ、最初のバイトが上位ビットを占めます。
  2. データが3バイト未満の場合、バッファ内の残りのビットは0で埋められます。次に、毎回6ビットを取り出し、ルックアップテーブルの値に従ってエンコードされた出力として対応する文字を選択します。
  3. すべての入力データの変換が完了するまで続けます。
  4. 最後に2つの入力データが残っている場合は、エンコード結果の後に「=」を追加します。
  5. 最後に入力データが1つ残っている場合は、エンコード結果の後に2 "="を追加します。
  6. データが残っていない場合は、データ復元の正確性を確保するために、何も追加しないでください。

3.3.Pythonの使用法

Pythonの組み込みbase64モジュールは、base64を直接エンコードおよびデコードできます

注:base64エンコーディングの場合、ASCIIまたはバイナリデータに含まれる文字のいずれか

In [1]: import base64

In [2]: base64.b64encode(b'hello world')
Out[2]: b'aGVsbG8gd29ybGQ='

In [3]: base64.b64decode(b'aGVsbG8gd29ybGQ=')
Out[3]: b'hello world'

4. MD5(メッセージダイジェストアルゴリズム)

メッセージダイジェストアルゴリズム5(メッセージダイジェストアルゴリズム)。よく言われる「MD5暗号化」は情報ダイジェストアルゴリズムです。

md5は実際にはアルゴリズムです。文字列、ファイル、または圧縮パッケージを配置できます。md5を実行した後、固定長の128ビット文字列を生成できます。この文字列は基本的に一意です。

4.1。機能

  1. 圧縮率:任意の長さのデータの場合、計算されたMD5値の長さは固定されています。
  2. 計算が簡単:元のデータからMD5値を簡単に計算できます。
  3. 変更防止:元のデータを変更すると、1バイトだけが変更された場合でも、取得されるMD5値は大きく異なります。
  4. 強力な衝突防止:元のデータとそのMD5値を知っていると、同じMD5値を持つデータ(つまり、偽のデータ)を見つけることは非常に困難です。
  5. 不可逆性:指紋は人それぞれです。この人を見ると、指紋などの情報や固有の対応がわかりますが、指紋を1つだけ見ると、その人の外見や身元などを確認したり読み取ったりすることはできません。情報。

栗を取る:私は世界に1人しかいませんが、女の子は非常にたくさんいます。私が限られていると、ほとんど無限の女の子がいるので、非常に多くの(100人以上の)女の子に対処できる可能性があります。これは理論的には確かに真実です。それは機能しますが、実際には...

4.2.Pythonの使用法

MD5モジュールはpython3で削除されたため、python3でのhashlibmd5操作モジュールを使用します

import hashlib

# 待加密信息
str = '这是一个测试'

# 创建md5对象
hl = hashlib.md5()

# 此处必须声明encode
# 若写法为hl.update(str)  报错为: Unicode-objects must be encoded before hashing
hl.update(str.encode(encoding='utf-8'))

print('MD5加密前为 :' + str)
print('MD5加密后为 :' + hl.hexdigest())

運転結果

MD5加密前为 :这是一个测试
MD5加密后为 :cfca700b9e09cf664f3ae80733274d9f

md5の長さ。デフォルトは128ビットで、128の0と1のバイナリ文字列です。そのような表現はとても不親切です。したがって、2進数は16進数に変換され、4ビットごとに16進数が表されるため、128/4 = 32は16進数に変換され、32ビットになります。

インターネット上にまだ16ビットのmd5があるのはなぜですか?

実際、16ビットの長さは32ビットのmd5値から導出されます。これは、32ビットmd5の最初の8ビットを削除し、最後の8ビットを削除することによって取得されます。


5.Python暗号化ライブラリPyCryptodome

PyCryptoは、Pythonで暗号化するための最も有名なサードパーティのソフトウェアパッケージであり、多くの暗号化アルゴリズムの使用を提供します。残念ながら、その開発作業は2012年に終了しました。

幸い、PyCryptoに代わるプロジェクトのブランチであるPyCrytodomeがあります。

5.1。インストールとインポート

インストールする前に、Microsoft Visual c ++ 2015をインストールする必要があります

Linuxにインストールするには、次のpipコマンドを使用できます。

pip install pycryptodome

インポート:

import Crypto

Windowsシステムへのインストールは少し異なります。

pip install pycryptodomex

インポート:

import Cryptodome

6.DES

DESアルゴリズムは、暗号システムの対称暗号システムであり、American Data EncryptionStandardとしても知られています。

DESはブロック暗号化アルゴリズムです。一般的なDESは、64ビットブロックでデータを暗号化します。暗号化と復号化にも同じアルゴリズムが使用されます。

DESアルゴリズムには、キー、データ、モードの3つの入力パラメーターがあります。キーはDESアルゴリズムの動作キーである合計7バイトと56ビットです。データは暗号化または復号化されるデータである8バイトと64ビットです。モードはDESの動作モードであり、2つあります。タイプ:暗号化または復号化。

キーの長さは64ビットで、キーは実際にはDES操作に関与する56ビットです(8、16、24、32、40、48、56、および64ビットはチェック桁であるため、各キーの奇数は1の数)、グループ化された平文グループと56ビットのキーは、暗号文グループを形成するためにビットごとに置き換えられるか交換されます。

6.1.Pythonの使用法

# 导入DES模块
from Cryptodome.Cipher import DES
import binascii

# 这是密钥
key = b'abcdefgh'
# 需要去生成一个DES对象
des = DES.new(key, DES.MODE_ECB)
# 需要加密的数据
text = 'python spider!'
text = text + (8 - (len(text) % 8)) * '='

# 加密的过程
encrypto_text = des.encrypt(text.encode())
encrypto_text = binascii.b2a_hex(encrypto_text)
print(encrypto_text)

7.3DES

3DES(またはトリプルDES)は、トリプルデータ暗号化アルゴリズム(TDEA、トリプルデータ暗号化アルゴリズム)ブロック暗号の総称です。これは、DES暗号化アルゴリズムを各データブロックに3回適用することと同じです。

コンピュータの計算能力の向上により、元のDES暗号の鍵の長さは力ずくで解読されやすくなります。3DESは、比較的単純な方法を提供するように設計されています。つまり、新しいブロック暗号アルゴリズムを設計するのではなく、DESのキーの長さを増やすことで同様の攻撃を回避します。

3DES(つまり、トリプルDES)は、DESからAESに移行するための暗号化アルゴリズムです(1999年にNISTは移行暗号化標準として3-DESを指定しました)。暗号化アルゴリズムは次のように実装されます。Ek()とDk()がDESアルゴリズム暗号化および復号化プロセスでは、KはDESアルゴリズムで使用されるキーを表し、Mはプレーンテキストを表し、Cは暗号テキストを表します。

3DES暗号化プロセスは次のとおりです。C= Ek3(Dk2(Ek1(M)))

3DES復号化プロセスは次のとおりです。M= Dk1(EK2(Dk3(C)))


8. AES

Advanced Encryption Standard(英語:Advanced Encryption Standard、略称:AESは、暗号化ではRijndael暗号化とも呼ばれ、米国連邦政府によって採用されているブロック暗号化標準です。この標準は、多くの関係者によって分析され、世界中で広く使用されている元のDESを置き換えるために使用されます。5年間の選択プロセスの後、Advanced Encryption Standardは、米国国立標準技術研究所(NIST)によって2001年11月26日にFIPS PUB 197で公開され、2002年5月26日に有効な標準になりました。2006年、Advanced Encryption Standardは、対称鍵暗号化で最も人気のあるアルゴリズムの1つになりました。

AESは、ソフトウェアとハ​​ードウェアですばやく暗号化および復号化でき、実装が比較的簡単で、必要なメモリはごくわずかです。新しい暗号化標準として、現在展開され、より広い範囲に適用されています。

8.1。機能

  1. 既知のすべての攻撃に抵抗します。
  2. 複数のプラットフォームでの高速でコンパクトなコーディング。
  3. デザインはシンプルです。

image.png

AESはブロック暗号です。ブロック暗号は、平文をグループに分割することです。各グループの長さは同じです。データのグループが暗号化されるたびに、平文全体が暗号化されます。AES標準仕様では、パケット長は128ビットのみです。つまり、各パケットは16バイト(1バイトあたり8ビット)です。キーの長さは、128ビット、192ビット、または256ビットにすることができます。キーの長さが異なり、推奨される暗号化ラウンドの数も異なります。

128ビットが一般的に使用されます

8.2.Pythonの実装

from Cryptodome.Cipher import AES
from Cryptodome import Random
from binascii import b2a_hex  

# 要加密的明文
data = '南来北往'
# 密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.
# 目前AES-128足够用
key = b'this is a 16 key'
# 生成长度等于AES块大小的不可重复的密钥向量
iv = Random.new().read(AES.block_size)

# 使用key和iv初始化AES对象, 使用MODE_CFB模式
mycipher = AES.new(key, AES.MODE_CFB, iv)
# 加密的明文长度必须为16的倍数,如果长度不为16的倍数,则需要补足为16的倍数
# 将iv(密钥向量)加到加密的密文开头,一起传输
ciphertext = iv + mycipher.encrypt(data.encode())

# 解密的话要用key和iv生成新的AES对象
mydecrypt = AES.new(key, AES.MODE_CFB, ciphertext[:16])
# 使用新生成的AES对象,将加密的密文解密
decrypttext = mydecrypt.decrypt(ciphertext[16:])


print('密钥k为:', key)
print('iv为:', b2a_hex(ciphertext)[:16])
print('加密后数据为:', b2a_hex(ciphertext)[16:])
print('解密后数据为:', decrypttext.decode())

演算結果:

密钥k为: b'this is a 16 key'
iv为: b'a78a177cffd50878'
加密后数据为: b'33f61e7678c25d795d565d40f2f68371da051202'
解密后数据为: 南来北往

9.RSA

RSA暗号化アルゴリズムは1種類非对称加密算法です。RSAは、公開鍵暗号化と電子商取引で広く使用されています。

このアルゴリズムは、数論の非常に単純な事実に基づいています。2つの大きな素数を乗算するのは簡単ですが、その時点で積を因数分解するのは非常に難しいため、積は暗号化キーとして開示できます。公開鍵と2つの​​大きな素数配列が秘密鍵を合成します。公開鍵は誰でも使用できるように解放可能であり、秘密鍵は復号化のために自分が所有しています。

9.1。非対称暗号化

通常、RSAなどの一般的な方法は、openssl、keytools、およびその他のツールを使用して、公開鍵と秘密鍵のペアを生成することです。公開鍵で暗号化されたデータは秘密鍵で復号化でき、その逆も可能です(データは秘密鍵は公開鍵の復号化にすることもできます)。

実際の使用では、秘密鍵は通常、発行者の手に保管され、秘密であり、外部に開示されません。公開鍵のみが外部に公開され、秘密鍵の所有者のみがデータを復号化できます。 。この暗号化方式は、復号化されたキーを送信する必要がないため、安全率が高く、送信プロセス中にキーが傍受されるリスクがなく、暗号文を解読することはほとんど不可能です。

ただし、アルゴリズムの効率が低いため、非常に重要なデータの暗号化によく使用され、対称暗号化と組み合わせて使用​​されることが多く、対称暗号化の鍵を暗号化するために非対称暗号化の鍵が使用されます。

9.2.Pythonの実装

まず、rsaモジュールをインストールする必要があります。

pip install rsa

また、RSA暗号化アルゴリズムの特性上、RSA公開鍵と秘密鍵はすべて10進数ですが、公開鍵の値は16進数で格納されることが多いため、int()10進数に変換する必要があります。

import rsa
import binascii

# 使用网页中获得的n和e值,将明文加密
def rsa_encrypt(rsa_n, rsa_e, message):
    # 用n值和e值生成公钥
    key = rsa.PublicKey(rsa_n, rsa_e)
    # 用公钥把明文加密
    message = rsa.encrypt(message.encode(), key)
    # 转化成常用的可读性高的十六进制
    message = binascii.b2a_hex(message)
    # 将加密结果转化回字符串并返回
    return message.decode()

# RSA的公钥有两个值n和e,我们在网站中获得的公钥一般就是这样的两个值。
# n常常为长度为256的十六进制字符串
# e常常为十六进制‘10001’
pubkey_n = '8d7e6949d411ce14d7d233d7160f5b2cc753930caba4d5ad24f923a505253b9c39b09a059732250e56c594d735077cfcb0c3508e9f544f101bdf7e97fe1b0d97f273468264b8b24caaa2a90cd9708a417c51cf8ba35444d37c514a0490441a773ccb121034f29748763c6c4f76eb0303559c57071fd89234d140c8bb965f9725'
pubkey_e = '10001'
# 需要将十六进制转换成十进制
rsa_n = int(pubkey_n, 16)
rsa_e = int(pubkey_e, 16)
# 要加密的明文
message = '南北今天很忙'

print("公钥n值长度:", len(pubkey_n))
print(rsa_encrypt(rsa_n, rsa_e, message))

演算結果:

公钥n值长度: 256
480f302eed822c8250256511ddeb017fcb28949cc05739ae66440eecc4ab76e7a7b2f1df398aefdfef2b9bfce6d6152bf6cc1552a0ed8bebee9e094a7ce9a52622487a6412632144787aa81f6ec9b96be95890c4c28a31b3e8d9ea430080d79297c5d75cd11df04df6e71b237511164399d72ccb2f4c34022b1ea7b76189a56e

 

おすすめ

転載: blog.csdn.net/weixin_42575020/article/details/107788550