加密算法
對稱加密
??加密過程的每一步都是可逆的。加密和解密用的是同一組密鑰线婚。異或是最簡單的對稱加密算法塞弊。
//XOR 異或運算,要求plain和key的長度相同
func XOR(plain string, key []byte) string {
bPlain := []byte(plain)
bCipher := make([]byte, len(key))
for i, k := range key {
bCipher[i] = k ^ bPlain[i]
}
cipher := string(bCipher)
return cipher
}
??DES(Data Encryption Standard)數(shù)據(jù)加密標準饰抒,是目前最為流行的加密算法之一诀黍。對原始數(shù)據(jù)(明文)進行分組,每組64位枣宫,最后一組不足64位時按一定規(guī)則填充吃环。每一組上單獨施加DES算法。
DES子密鑰生成
??初始密鑰64位歇拆,實際有效位56位范咨,每隔7位有一個校驗位渠啊。根據(jù)初始密鑰生成16個48位的子密鑰。
??N取值從1到16贯溅,N和x有固定的映射表。
DES加密過程
??L1, R1 = f(L0, R0, K1),依此循環(huán)鄙麦,得到L16和R16镊折。
??S盒替換。輸入48位骂因,輸出32位赃泡。各分為8組,輸入每組6位,輸出每組4位蹦肴。分別在每組上施加S盒替換阴幌,一共8個S盒。
DES加密過程
??分組模式渊抽。CBC(Cipher Block Chaining )密文分組鏈接模式懒闷,將當前明文分組與前一個密文分組進行異或運算栈幸,然后再進行加密。其他分組模式還有ECB, CTR, CFR, OFB玩焰。
func DesEncryptCBC(text string, key []byte) (string, error) {
src := []byte(text)
block, err := des.NewCipher(key) //用des創(chuàng)建一個加密器cipher
if err != nil {
return "", err
}
blockSize := block.BlockSize() //分組的大小芍锚,blockSize=8
src = common.ZeroPadding(src, blockSize) //填充
out := make([]byte, len(src)) //密文和明文的長度一致
encrypter := cipher.NewCBCEncrypter(block, key) //CBC分組模式加密
encrypter.CryptBlocks(out, src)
return hex.EncodeToString(out), nil
}
func DesDecryptCBC(text string, key []byte) (string, error) {
src, err := hex.DecodeString(text) //轉成[]byte
if err != nil {
return "", err
}
block, err := des.NewCipher(key)
if err != nil {
return "", err
}
out := make([]byte, len(src)) //密文和明文的長度一致
encrypter := cipher.NewCBCDecrypter(block, key) //CBC分組模式解密
encrypter.CryptBlocks(out, src)
out = common.ZeroUnPadding(out) //反填充
return string(out), nil
}
??AES(Advanced Encryption Standard)高級加密標準,旨在取代DES默刚。
非對稱加密
- 使用公鑰加密羡棵,使用私鑰解密。
- 公鑰和私鑰不同皂冰。
- 公鑰可以公布給所有人秃流。
- 私鑰只有自己保存。
- 相比于對稱加密概说,運算速度非常慢嚣伐。
??對稱加密和非對稱加密結合使用的案例轩端。小明要給小紅傳輸機密文件,他倆先交換各自的公鑰基茵,然后:
- 小明生成一個隨機的AES口令拱层,然后用小紅的公鑰通過RSA加密這個口令,并發(fā)給小紅根灯。
- 小紅用自己的RSA私鑰解密得到AES口令烙肺。
- 雙方使用這個共享的AES口令用AES加密通信。
??RSA是三個發(fā)明人名字的縮寫:Ron Rivest兆旬,Adi Shamir怎栽,Leonard Adleman。密鑰越長脚祟,越難破解。 目前768位的密鑰還無法破解(至少沒人公開宣布)为黎。因此可以認為1024位的RSA密鑰基本安全行您,2048位的密鑰極其安全娃循。RSA的算法原理主要用到了數(shù)論。
RSA加密過程
- 隨機選擇兩個不相等的質(zhì)數(shù)p和q捌斧。p=61, q=53
- 計算p和q的乘積n。n=3233
- 計算n的歐拉函數(shù)φ(n) = (p-1)(q-1)妇押。 φ(n) =3120
- 隨機選擇一個整數(shù)e姓迅,使得1< e < φ(n)敲霍,且e與φ(n) 互質(zhì)队贱。e=17
- 計算e對于φ(n)的模反元素d柱嫌,即求解ed+ φ(n)y=1屯换。d=2753, y=-15
- 將n和e封裝成公鑰,n和d封裝成私鑰嘉抓。公鑰=(3233晕窑,17),公鑰=(3233杨赤,2753)
// RSA加密
func RsaEncrypt(origData []byte) ([]byte, error) {
//解密pem格式的公鑰
block, _ := pem.Decode(publicKey)
if block == nil {
return nil, errors.New("public key error")
}
// 解析公鑰
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) //目前的數(shù)字證書一般都是基于ITU(國際電信聯(lián)盟)制定的X.509標準
if err != nil {
return nil, err
}
// 類型斷言
pub := pubInterface.(*rsa.PublicKey)
//加密
return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}
// RSA解密
func RsaDecrypt(ciphertext []byte) ([]byte, error) {
//解密
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, errors.New("private key error!")
}
//解析PKCS1格式的私鑰
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
// 解密
return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
}
??ECC(Elliptic Curve Cryptography)橢圓曲線加密算法截汪,相比RSA衙解,ECC可以使用更短的密鑰焰枢,來實現(xiàn)與RSA相當或更高的安全。定義了橢圓曲線上的加法和二倍運算暑椰。橢圓曲線依賴的數(shù)學難題是:k為正整數(shù)拟淮,P是橢圓曲線上的點(稱為基點), k*P=Q , 已知Q和P,很難計算出k角虫。
func genPrivateKey() (*ecies.PrivateKey, error) {
pubkeyCurve := elliptic.P256() // 初始化橢圓曲線
// 隨機挑選基點,生成私鑰
p, err := ecdsa.GenerateKey(pubkeyCurve, rand.Reader) //用golang標準庫生成公私鑰對
if err != nil {
return nil, err
} else {
return ecies.ImportECDSA(p), nil //轉換成以太坊的公私鑰對
}
}
//ECCEncrypt 橢圓曲線加密
func ECCEncrypt(plain string, pubKey *ecies.PublicKey) ([]byte, error) {
src := []byte(plain)
return ecies.Encrypt(rand.Reader, pubKey, src, nil, nil)
}
//ECCDecrypt 橢圓曲線解密
func ECCDecrypt(cipher []byte, prvKey *ecies.PrivateKey) (string, error) {
if src, err := prvKey.Decrypt(cipher, nil, nil); err != nil {
return "", err
} else {
return string(src), nil
}
}
哈希算法
哈希函數(shù)的基本特征
- 輸入可以是任意長度委造。
- 輸出是固定長度。
- 根據(jù)輸入很容易計算出輸出昏兆。
- 根據(jù)輸出很難計算出輸入(幾乎不可能)。
- 兩個不同的輸入幾乎不可能得到相同的輸出隶债。
??SHA(Secure Hash Algorithm) 安全散列算法跑筝,是一系列密碼散列函數(shù)曲梗,有多個不同安全等級的版本:SHA-1,SHA-224,SHA-256,SHA-384,SHA-512。其作用是防偽裝愧旦,防竄擾定罢,保證信息的合法性和完整性笤虫。
sha-1算法大致過程
- 填充。使得數(shù)據(jù)長度對512求余的結果為448耕皮。
- 在信息摘要后面附加64bit凌停,表示原始信息摘要的長度。
- 初始化h0到h4台诗,每個h都是32位赐俗。
- h0到h4歷經(jīng)80輪復雜的變換。
- 把h0到h4拼接起來粱快,構成160位叔扼,返回。
func Sha1(data string) string {
sha1 := sha1.New()
sha1.Write([]byte(data))
return hex.EncodeToString(sha1.Sum(nil))
}
??MD5(Message-Digest Algorithm 5)信息-摘要算法5瓜富,算法流程跟SHA-1大體相似。MD5的輸出是128位与柑,比SHA-1短了32位价捧。MD5相對易受密碼分析的攻擊,運算速度比SHA-1快脯倚。
func Md5(data string) string {
md5 := md5.New()
md5.Write([]byte(data))
return hex.EncodeToString(md5.Sum(nil))
}
哈希函數(shù)的應用場景
- 用戶密碼的存儲椎眯。
- 文件上傳/下載完整性校驗胳岂。
- mysql大字段的快速對比。
數(shù)字簽名
??比特幣中驗證交易記錄的真實性用的就是數(shù)字簽名乳丰。先hash再用私鑰加密的原因是:非對稱加密計算量比較大,先hash可以把原始數(shù)據(jù)轉一條很短的信息,提高計算效率夜郁。