zoukankan      html  css  js  c++  java
  • aes-256-gcm_python3_php7_golang

    aes-256-gcm_python3_php7_golang

    转载注明来源: 本文链接 来自osnosn的博客,写于 2021-02-07.

    以下的,不同语言的加解密函数,输出内容可以互通。

    python3

    #!/usr/bin/python3
    ### coding: utf-8
    
    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
    import cryptography.exceptions
    import binascii
    import base64
    import os
    
    def encrypt_aes256gcm(key, ciphertext, aad):
        '''
        aes-256-gcm 加密
          key: 为str,hex字符串,64字符(32字节)
          aad: 为str,hex字符串,32字符(16字节)
          ciphertext: 为bytes, 明文
        返回: 为bytes, base64 的密文
        '''
        aes_gcm_ivlen = 12
        key_bytes = binascii.unhexlify(key)
        aad_bytes = binascii.unhexlify(aad)
        data = ciphertext
        iv_bytes = os.urandom(aes_gcm_ivlen)
    
        aesgcm = AESGCM(key_bytes) # tag_length=16
        crypt_bytes = aesgcm.encrypt(iv_bytes, data, aad_bytes)
        return base64.b64encode(iv_bytes + crypt_bytes)
    
    
    def decrypt_aes256gcm(key, ciphertext, aad):
        '''
        aes-256-gcm 解密
          key: 为str,hex字符串,64字符(32字节)
          aad: 为str,hex字符串,32字符(16字节)
          ciphertext: 为bytes, base64 的密文
        返回: bytes 的明文, 或者解密失败 返回 b''
        '''
        aes_gcm_ivlen = 12
        key_bytes = binascii.unhexlify(key)
        aad_bytes = binascii.unhexlify(aad)
        try:
            data = base64.b64decode(ciphertext)
        except binascii.Error as e:
            #print(e)
            return b''
        iv_bytes = data[0:aes_gcm_ivlen]
        data = data[aes_gcm_ivlen:]
    
        aesgcm = AESGCM(key_bytes) # tag_length=16
        try:
            text_bytes = aesgcm.decrypt(iv_bytes, data, aad_bytes)
        except cryptography.exceptions.InvalidTag as e:
            return b''
        return text_bytes
    
    if __name__ =='__main__':
        key='1100222233334444555566667777888899990000aaaabbbbccccddddeeeeffff'
        aad='22223311223311221122331122331122'
        ciphertext = encrypt_aes256gcm(key, b"a secret message!", aad)
        print(ciphertext)
        ssss=b'YO4uAtkNBFpKF8GRni8tT2IW6WUQRox8D1ujcCkPKtxYsbWHDdInvvjxqzN/'
        ciphertext = decrypt_aes256gcm(key, ssss,aad)
        print(ciphertext)

    php7.1 或以上

    <?php
    
    function encrypt_aes256gcm($key, $ciphertext, $aad){
       // 加密
       //  $key: hex字符串,64字符(32字节)
       //  $aad: hex字符串,32字符(16字节)
       // 返回 base64编码的密文
       $cipher='aes-256-gcm';
       $ivlen= openssl_cipher_iv_length($cipher); // 12
       $iv=openssl_random_pseudo_bytes($ivlen);
       $key=hex2bin($key);
       $aad=hex2bin($aad);
       $ss=openssl_encrypt($ciphertext,$cipher,$key,OPENSSL_RAW_DATA,$iv,$tag,$aad,16);
       $ssss=$iv.$ss.$tag;
       return base64_encode($ssss);
    }
    function decrypt_aes256gcm($key, $ciphertext, $aad){
       // 解密
       //  $key: hex字符串,64字符(32字节)
       //  $aad: hex字符串,32字符(16字节)
       // 返回 明文,或空
       $cipher='aes-256-gcm';
       $ivlen= openssl_cipher_iv_length($cipher); // 12
       if(preg_match('/^[/+=0-9a-zA-Z]+$/',$ciphertext)) {
          $text1=base64_decode($ciphertext);
          $tag=substr($text1,-16);
          $iv =substr($text1,0,$ivlen);
          $text1=substr($text1,$ivlen,-16);
          $key=hex2bin($key);
          $aad=hex2bin($aad);
          $txt01=openssl_decrypt($text1,$cipher,$key,OPENSSL_RAW_DATA,$iv,$tag,$aad);
          if($txt01===false) return '';
          return $txt01;
       } else return '';
    }
    
    $key='1100222233334444555566667777888899990000aaaabbbbccccddddeeeeffff';
    $aad='22223311223311221122331122331122';
    $ciphertext = encrypt_aes256gcm($key, b"a secret message!", $aad);
    echo $ciphertext ."
    ";
    $ssss=b'YO4uAtkNBFpKF8GRni8tT2IW6WUQRox8D1ujcCkPKtxYsbWHDdInvvjxqzN/';
    $ciphertext = decrypt_aes256gcm($key, $ssss, $aad);
    echo $ciphertext ."
    ";

    golang

    package main
    
    //go build -ldflags "-w -s"  -s:去掉符号信息 -w:去掉DWARF调试信息
    
    import (
            "crypto/aes"
            "crypto/cipher"
            "crypto/rand"
            "encoding/base64"
            "encoding/hex"
            "errors"
            "fmt"
            "strings"
    )
    
    func en_aesgcm(hex_key string, plaintext []byte, hex_aad string) (string, error) {
            //秘钥长度按需:AES-128(16bytes)或者AES-256(32bytes)
            key, _ := hex.DecodeString(hex_key)
            aad, _ := hex.DecodeString(hex_aad)
    
            block, err := aes.NewCipher(key) //生成加解密用的block
            if err != nil {
                    return "", err
            }
            aesgcm, err := cipher.NewGCM(block)
            if err != nil {
                    return "", err
            }
            // 对IV有随机性要求,但没有保密性要求,所以常见的做法是将IV包含在加密文本当中
            iv := make([]byte, aesgcm.NonceSize())            // NonceSize=12
            rand.Read(iv)                                     //获取随机值
            ciphertext := aesgcm.Seal(iv, iv, plaintext, aad) //加密,密文为:iv+密文+tag
            //return base64.RawStdEncoding.EncodeToString(ciphertext), nil // 生成的BS64,无尾部的pad"="
            return base64.StdEncoding.EncodeToString(ciphertext), nil // 生成的BS64
    }
    func de_aesgcm(hex_key string, cipherbs64 string, hex_aad string) ([]byte, error) {
            //秘钥长度按需:AES-128(16bytes)或者AES-256(32bytes)
            key, _ := hex.DecodeString(hex_key)
            aad, _ := hex.DecodeString(hex_aad)
    
            cipherbs64 = strings.TrimRight(cipherbs64, "=")
            ciphertext, err := base64.RawStdEncoding.DecodeString(cipherbs64) // 要先去掉尾部的pad"=",否则解bs64失败
            if err != nil {
                    return []byte(""), err
            }
            block, err := aes.NewCipher(key) //生成加解密用的block
            if err != nil {
                    return []byte(""), err
            }
            aesgcm, err := cipher.NewGCM(block)
            if err != nil {
                    return []byte(""), err
            }
            if len(ciphertext) <= aesgcm.NonceSize() { // 长度应该>iv
                    return []byte(""), errors.New("string: too short") //解密失败
            }
    
            iv := ciphertext[:aesgcm.NonceSize()]        //分离出IV
            ciphertext = ciphertext[aesgcm.NonceSize():] // 密文+tag
            plaintext, err := aesgcm.Open(nil, iv, ciphertext, aad)
            return plaintext, err         //err!=nil时,plaintext=byte[]("")
    }
    
    func main() {
            key := "1234567812345678123456781234567812345678123456781234567812345678"
            aad := "11223344556677881122334455667788"
            fmt.Printf("len(key),len(aad): %d,%d 
    
    ", len(key), len(aad))
    
            plaintext := []byte("this is a security text12")
            v1, err := en_aesgcm(key, plaintext, aad)
            fmt.Printf("加密结果: %s , %q
    
    ", v1, err)
    
            v1 = "rkaaPGZmO/KtQrbePAjqxzN6y9yvmf4EFM6b/8rgkjp5RtOXgKU7m7qQTA3s40tHBfScOlc="
            v3, err := de_aesgcm(key, v1, aad)
            fmt.Printf("解密: %q , %q
    
    ", v3, err)
    }
  • 相关阅读:
    定时器
    javascript之循环保存数值
    Web 前端之HTML和CSS
    [讲解]容斥原理
    [vijos1048]送给圣诞夜的贺卡<DFS剪枝>
    [vijos1145]小胖吃巧克力<概率dp>
    [noip2012]国王游戏<贪心+高精度>
    [codevs3118]高精度除法<高精度>
    [noip2016]组合数问题<dp+杨辉三角>
    [codevs2370]小机房的树<LCA>
  • 原文地址:https://www.cnblogs.com/pu369/p/15409904.html
Copyright © 2011-2022 走看看