java-python aes-gcm 加密说明

python-java 的 AES-GCM 加解说明

内容

  1. 说明
  2. 测试数据
  3. python-PyCryptodome版本
  4. python-cryptography版本
  5. java版本

说明

  1. AES-GCM是一种NIST标准的认证加密算法, 是一种能够同时保证数据的保密性、 完整性和真实性的一种加密模式。它最广泛的应用是在TLS中。
  2. GCM详细说明
测试数据
AES加密模式:AEAD_AES_256_GCM

AES密钥:
aesKey = 1d35eefc2b8207d615028d056ce5296c
附加数据:
associatedData = 12345
随机数据:nonceData
nonceData = 1234567812345678
数据明文: 1234561234565
数据密文:X3lkQaqdASpIF0+XsOjwUhfCZdvXh3RQFXsH8o8=

python demo--PyCryptodome版本
import base64
from Crypto.Cipher import AES

aes_key = '1d35eefc2b8207d615028d056ce5296c'
associatedData = "12345"
nonce = "1234567812345678"

def aes_en_gcm_func():
    de_data = '1234561234565'
    cipher = AES.new(aes_key.encode(), AES.MODE_GCM, nonce=nonce.encode())
    cipher.update(associatedData.encode())
    ct, tag = cipher.encrypt_and_digest(de_data.encode('utf-8'))
    return base64.b64encode(ct + tag).decode('utf-8')


def aes_de_gcm_func():
    en_data = 'X3lkQaqdASpIF0+XsOjwUhfCZdvXh3RQFXsH8o8='
    cipher = AES.new(aes_key.encode(), AES.MODE_GCM, nonce=nonce.encode())
    cipher.update(associatedData.encode())
    en_data = base64.b64decode(en_data.encode('utf-8'))
    auth_tag = en_data[-16:]
    _en_data = en_data[:-16]
    plaintext = cipher.decrypt_and_verify(_en_data, auth_tag)
    return plaintext.decode()
python demo--cryptography 版本
import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

aes_key = '1d35eefc2b8207d615028d056ce5296c'
associatedData = "12345"
nonce = "1234567812345678"

def st_aes_en_func():
    de_data = '1234561234565'
    aesgcm = AESGCM(aes_key.encode())
    ct = aesgcm.encrypt(nonce.encode(), de_data.encode(), associatedData.encode())
    return base64.b64encode(ct).decode('utf-8')


def st_aes_de_func():
    en_data = 'X3lkQaqdASpIF0+XsOjwUhfCZdvXh3RQFXsH8o8='
    en_data = base64.b64decode(en_data.encode('utf-8'))
    aesgcm = AESGCM(aes_key.encode())
    ct = aesgcm.decrypt(nonce.encode(), en_data, associatedData.encode())
    return ct.decode()
java demo
package tools;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AesUtil {
    static final int KEY_LENGTH_BYTE = 32;
    static final int TAG_LENGTH_BIT = 128;
    private final byte[] aesKey;

    public AesUtil(byte[] key) {
        if (key.length != KEY_LENGTH_BYTE) {
            throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
        }
        this.aesKey = key;
    }

    public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
            throws GeneralSecurityException, IOException {
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

            SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);

            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData);

            return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(e);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public String encryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
            throws GeneralSecurityException, IOException{
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

            SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);

            cipher.init(Cipher.ENCRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData);

//            return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
            return new String(Base64.getEncoder().encode(cipher.doFinal(ciphertext.getBytes())), "utf-8");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(e);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw new IllegalArgumentException(e);
        }
    }
    public static void main(String[] args) throws Exception {
        String key = "1d35eefc2b8207d615028d056ce5296c";
        String associatedData = "12345";
        String nonce = "1234567812345678";
        AesUtil aesUtils = new AesUtil(key.getBytes());

        String enData = aesUtils.encryptToString(associatedData.getBytes(), nonce.getBytes(), "1234561234565");
        System.out.println("加密后密文:" + enData);
        String deData = aesUtils.decryptToString(associatedData.getBytes(), nonce.getBytes(), enData);
        System.out.println("解密后明文:" + deData);

    }

}


  • 参考
  • https://www.pycryptodome.org/en/latest/index.html
  • https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_2.shtml
  • https://blog.csdn.net/T0mato_/article/details/53160772

你可能感兴趣的:(java-python aes-gcm 加密说明)