function Encrypt_AEAD_AES_256_GCM(const AData, AKey, AIV, AAD: TBytes; out AEnCryptData, ATag: TBytes): Boolean; var Ctx: PEVP_CIPHER_CTX; Len: Integer; DataLen: Integer; begin Result := False; Len := 0; DataLen := 0; SetLength(AEnCryptData, 8192);
Ctx := EVP_CIPHER_CTX_new(); try EVP_EncryptInit_ex(Ctx, EVP_aes_256_gcm(), nil, nil, nil); // Set IV length if default 96 bits is not appropriate (12byte) EVP_CIPHER_CTX_ctrl(Ctx, EVP_CTRL_GCM_SET_IVLEN, Length(AIV), nil); EVP_EncryptInit_ex(Ctx, nil, nil, @AKey[0], @AIV[0]);
if EVP_EncryptUpdate(Ctx, nil, @Len, @AAD[0], Length(AAD)) <> 1 then Exit(False); if EVP_EncryptUpdate(Ctx, @AEnCryptData[0], @Len, @AData[0], Length(AData)) <> 1 then Exit(False);
DataLen := Len;
if EVP_EncryptFinal_ex(Ctx, @AEnCryptData[DataLen], @Len) <> 1 then Exit(False);
//get tag SetLength(ATag, 16); if EVP_CIPHER_CTX_ctrl(Ctx, EVP_CTRL_GCM_GET_TAG, 16, @ATag[0]) <> 1 then Exit(False);
Result := True; finally EVP_CIPHER_CTX_free(Ctx); end; end;
class function TgoOpenSSLHelper.Decrypt_AEAD_AES_256_GCM(const AData, AKey, AIV, AAD, ATag: TBytes; out ADeCryptData: TBytes): Boolean; var Ctx: PEVP_CIPHER_CTX; Len: Integer; DataLen: Integer; TAG: TBytes; begin Result := False; Len := 0; DataLen := 0; SetLength(ADeCryptData, 8192);
Ctx := EVP_CIPHER_CTX_new(); try EVP_DecryptInit_ex(Ctx, EVP_aes_256_gcm, nil, nil, nil); // Set IV length if default 96 bits is not appropriate (12byte) EVP_CIPHER_CTX_ctrl(Ctx, EVP_CTRL_GCM_SET_IVLEN, Length(AIV), nil); EVP_DecryptInit_ex(Ctx, nil, nil, @AKey[0], @AIV[0]);
if EVP_DecryptUpdate(Ctx, nil, @Len, @AAD[0], Length(AAD)) <> 1 then Exit(False); if EVP_DecryptUpdate(Ctx, @ADeCryptData[0], @Len, @AData[0], Length(AData)) <> 1 then Exit(False);
DataLen := Len; //set tag if EVP_CIPHER_CTX_ctrl(Ctx, EVP_CTRL_GCM_SET_TAG, 16, @ATag[0]) <> 1 then Exit(False);
if EVP_DecryptFinal_ex(Ctx, @ADeCryptData[DataLen], @Len) <= 0 then Exit(False);
class function TgoOpenSSLHelper.CreateRSAPairKey(const APKCSFormat: Integer; out APrivateKey, APublicKey: TBytes): Boolean; var Bignum: PBIGNUM; BNGEN: PBN_GENCB; BIOPrivateKey: PBIO; BIOPublicKey: PBIO; RSA: PRSA; EVPKey: PEVP_PKEY; PrivateLen, PendingLen1: Integer; PublicLen, PendingLen2: Integer; begin Result := False; PrivateLen := 0; PublicLen := 0; PendingLen1 := 0; PendingLen2 := 0;
EVPKey := EVP_PKEY_new; if EVPKey = nil then Exit; BIOPrivateKey := BIO_new(BIO_s_mem); BIOPublicKey := BIO_new(BIO_s_mem);
Bignum := BN_new; if Bignum = nil then Exit; BNGEN := BN_GENCB_new; if BNGEN = nil then Exit; try if BN_set_word(Bignum, RSA_F4) <> 1 then Exit; RSA := RSA_new; if RSA = nil then Exit; try if RSA_generate_key_ex(RSA, RSA_KEY_BITS, Bignum, nil) <> 1 then Exit;
if APKCSFormat <> 8 then //PKCS1 begin if PEM_write_bio_RSAPrivateKey(BIOPrivateKey, RSA, nil, nil, 0, nil, nil) <> 1 then Exit; if PEM_write_bio_RSAPublicKey(BIOPublicKey, RSA) <> 1 then Exit; end else //PKCS8 begin if EVP_PKEY_assign(EVPKey, EVP_PKEY_RSA, RSA) <> 1 then Exit(False);
if PEM_write_bio_PKCS8PrivateKey(BIOPrivateKey, EVPKey, nil, nil, 0, nil, nil) <> 1 then Exit; if PEM_write_bio_PUBKEY(BIOPublicKey, EVPKey) <> 1 then Exit; end;
class function TgoOpenSSLHelper.EncrytByPublicKey_RSA_OAEP(const AData, APublicKey: TBytes; out AEnCryptData: TBytes): Boolean; var BIOPublicKey: PBIO; RSA: PRSA; DataLen: Integer; begin Result := False; //加密数据长度不能大于214,大于214的要分块处理,不懂 if Length(AData) > 214 then Exit;
try //支持pkcs1和pkcs8 if CompareMem(@PUBLICKEY_FLAG_PKCS1_START[1], @APublicKey[0], Length(PUBLICKEY_FLAG_PKCS1_START)) then RSA := PEM_read_bio_RSAPublicKey(BIOPublicKey, nil, nil, nil) else RSA := PEM_read_bio_RSA_PUBKEY(BIOPublicKey, nil, nil, nil);
if RSA = nil then Exit;
try DataLen := RSA_public_encrypt(Length(AData), @AData[0], @AEnCryptData[0], RSA, RSA_PKCS1_OAEP_PADDING); if (DataLen > 0) and (DataLen <= 256) then begin SetLength(AEnCryptData, DataLen); Result := True; end; finally EVP_PKEY_free(RSA); end;
finally BIO_free(BIOPublicKey); end; end;
//私钥解密
class function TgoOpenSSLHelper.DecrytByPrivateKey_RSA_OAEP(const AData, APrivateKey: TBytes; out ADeCryptData: TBytes): Boolean; var BIOPrivateKey: PBIO; RSA: PRSA; DataLen: Integer; begin Result := False; if Length(AData) < 10 then Exit; DataLen := 0; SetLength(ADeCryptData, 256);
BIOPrivateKey := BIO_new_mem_buf(@APrivateKey[0], Length(APrivateKey)); try //这个函数可以支持pkcs1和pkcs8 RSA := PEM_read_bio_RSAPrivateKey(BIOPrivateKey, nil, nil, nil); try DataLen := RSA_private_decrypt(Length(AData), @AData[0], @ADeCryptData[0], RSA, RSA_PKCS1_OAEP_PADDING); if (DataLen > 0) and (DataLen <= 214) then begin SetLength(ADeCryptData, DataLen); Result := True; end; finally EVP_PKEY_free(RSA); end; finally BIO_free(BIOPrivateKey); end; end;
----------------------------------------------
-