osnosn

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

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 ."\n";
$ssss=b'YO4uAtkNBFpKF8GRni8tT2IW6WUQRox8D1ujcCkPKtxYsbWHDdInvvjxqzN/';
$ciphertext = decrypt_aes256gcm($key, $ssss, $aad);
echo $ciphertext ."\n";

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 \n\n", len(key), len(aad))

        plaintext := []byte("this is a security text12")
        v1, err := en_aesgcm(key, plaintext, aad)
        fmt.Printf("加密结果: %s , %q\n\n", v1, err)

        v1 = "rkaaPGZmO/KtQrbePAjqxzN6y9yvmf4EFM6b/8rgkjp5RtOXgKU7m7qQTA3s40tHBfScOlc="
        v3, err := de_aesgcm(key, v1, aad)
        fmt.Printf("解密: %q , %q\n\n", v3, err)
}

转载注明来源: 本文链接 来自osnosn的博客.

posted on 2021-02-07 17:40  osnosn  阅读(744)  评论(0编辑  收藏  举报