加密算法

加密算法

对称加密

加密过程的每一步都是可逆的。加密和解密用的是同一组密钥。异或是最简单的对称加密算法。

//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)数据加密标准,是目前最为流行的加密算法之一。对原始数据(明文)进行分组,每组64位,最后一组不足64位时按一定规则填充。每一组上单独施加DES算法。 DES子密钥生成 初始密钥64位,实际有效位56位,每隔7位有一个校验位。根据初始密钥生成16个48位的子密钥。

N取值从1到16,N和x有固定的映射表。

DES加密过程

L1, R1 = f(L0, R0, K1),依此循环,得到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创建一个加密器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。

非对称加密

  • 使用公钥加密,使用私钥解密。

  • 公钥和私钥不同。

  • 公钥可以公布给所有人。

  • 私钥只有自己保存。

  • 相比于对称加密,运算速度非常慢。

对称加密和非对称加密结合使用的案例。小明要给小红传输机密文件,他俩先交换各自的公钥,然后:

  1. 小明生成一个随机的AES口令,然后用小红的公钥通过RSA加密这个口令,并发给小红。

  2. 小红用自己的RSA私钥解密得到AES口令。

  3. 双方使用这个共享的AES口令用AES加密通信。

RSA是三个发明人名字的缩写:Ron Rivest,Adi Shamir,Leonard Adleman。密钥越长,越难破解。 目前768位的密钥还无法破解(至少没人公开宣布)。因此可以认为1024位的RSA密钥基本安全,2048位的密钥极其安全。RSA的算法原理主要用到了数论。 RSA加密过程

  1. 随机选择两个不相等的质数p和q。p=61, q=53

  2. 计算p和q的乘积n。n=3233

  3. 计算n的欧拉函数φ(n) = (p-1)(q-1)。 φ(n) =3120

  4. 随机选择一个整数e,使得1< e < φ(n),且e与φ(n) 互质。e=17

  5. 计算e对于φ(n)的模反元素d,即求解ed+ φ(n)y=1。d=2753, y=-15

  6. 将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) //目前的数字证书一般都是基于ITU(国际电信联盟)制定的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可以使用更短的密钥,来实现与RSA相当或更高的安全。定义了椭圆曲线上的加法和二倍运算。椭圆曲线依赖的数学难题是:k为正整数,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
    }
}

哈希算法

哈希函数的基本特征

  1. 输入可以是任意长度。

  2. 输出是固定长度。

  3. 根据输入很容易计算出输出。

  4. 根据输出很难计算出输入(几乎不可能)。

  5. 两个不同的输入几乎不可能得到相同的输出。

SHA(Secure Hash Algorithm) 安全散列算法,是一系列密码散列函数,有多个不同安全等级的版本:SHA-1,SHA-224,SHA-256,SHA-384,SHA-512。其作用是防伪装,防窜扰,保证信息的合法性和完整性。 sha-1算法大致过程

  1. 填充。使得数据长度对512求余的结果为448。

  2. 在信息摘要后面附加64bit,表示原始信息摘要的长度。

  3. 初始化h0到h4,每个h都是32位。

  4. h0到h4历经80轮复杂的变换。

  5. 把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))
}

哈希函数的应用场景

  • 用户密码的存储。

  • 文件上传/下载完整性校验。

  • mysql大字段的快速对比。 数字签名

比特币中验证交易记录的真实性用的就是数字签名。先hash再用私钥加密的原因是:非对称加密计算量比较大,先hash可以把原始数据转一条很短的信息,提高计算效率。

 

 

posted @ 2022-09-10 22:55  屠魔的少年  阅读(2)  评论(0)    收藏  举报