使用 EVP 接口的 AES-GCM OpenSSL C 示例

2024-01-09

对于AES-GCM加密/解密,我尝试了这个,但是有问题。

ctx     = EVP_CIPHER_CTX_new();

//Get the cipher.
cipher  = EVP_aes_128_gcm ();


#define     GCM_IV      "000000000000"
#define     GCM_ADD     "0000"
#define     TAG_SIZE    16
#define     ENC_SIZE    64


//Encrypt the data first.
//Set the cipher and context only.
retv    = EVP_EncryptInit (ctx, cipher, NULL, NULL);

//Set the nonce and tag sizes.
//Set IV length. [Optional for GCM].

retv    = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, strlen((const char *)GCM_IV), NULL);

//Now initialize the context with key and IV. 
retv    = EVP_EncryptInit (ctx, NULL, (const unsigned char *)keybuf, (const unsigned char *)GCM_IV);

//Add Additional associated data (AAD). [Optional for GCM]
retv    = EVP_EncryptUpdate (ctx, NULL, (int *)&enclen, (const unsigned char *)GCM_ADD, strlen(GCM_ADD));

//Now encrypt the data.
retv    = EVP_EncryptUpdate (ctx, (unsigned char *)encm, (int *)&enclen, (const unsigned char *)msg, _tcslen (msg) *sizeof(Char));

//Finalize.
retv    = EVP_EncryptFinal (ctx, (unsigned char *)encm + enclen, (int *)&enclen2);
enclen  += enclen2;


//Append authentication tag at the end.
retv    = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_GET_TAG, TAG_SIZE, (unsigned char *)encm + enclen);

//DECRYPTION PART
//Now Decryption of the data.
//Then decrypt the data.
//Set just cipher.
retv    = EVP_DecryptInit(ctx, cipher, NULL, NULL);

//Set Nonce size.
retv    = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, strlen((const char *)GCM_IV), NULL);

//Set Tag from the data.
retv    = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_TAG, TAG_SIZE, (unsigned char *)encm + enclen);

//Set key and IV (nonce).
retv    = EVP_DecryptInit (ctx, NULL, (const unsigned char*)keybuf, (const unsigned char *)GCM_IV);

//Add Additional associated data (AAD).
retv    = EVP_DecryptUpdate (ctx, NULL, (int *)&declen, (const unsigned char *)GCM_ADD,
                             strlen((const char *)GCM_ADD));

//Decrypt the data.
retv    = EVP_DecryptUpdate (ctx, decm, (int *)&declen, (const unsigned char *)encm, enclen);


//Finalize.
retv    = EVP_DecryptFinal (ctx, (unsigned char*)decm + declen, (int *)&declen2);

这段代码运行良好(经过一些修改)。它正在加密和解密消息。 问题是,当在解密之前修改密文时,它仍然会解密文本(但是,错误的)。 根据我对认证加密的理解,在这种情况下,它不应该解密修改后的密文。

我哪里错了? 我可以获得使用 OpenSSL EVP 接口的 AES-GCM 的任何合适示例吗?


以下是每次更新调用时加密和解密 128 字节的示例:

  int howmany, dec_success, len;
  const EVP_CIPHER *cipher;
  switch(key_len)
  {
  case 128: cipher  = EVP_aes_128_gcm ();break;
  case 192: cipher  = EVP_aes_192_gcm ();break;
  case 256: cipher  = EVP_aes_256_gcm ();break;
  default:break;
  }
  // Encrypt
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  EVP_EncryptInit (ctx, cipher, KEY, IV);
  EVP_EncryptUpdate (ctx, NULL, &howmany, AAD, aad_len);
  len = 0;
  while(len <= in_len-128)
  {
     EVP_EncryptUpdate (ctx, CIPHERTEXT+len, &howmany, PLAINTEXT+len, 128);
     len+=128;
  }
  EVP_EncryptUpdate (ctx, CIPHERTEXT+len, &howmany, PLAINTEXT+len, in_len - len);
  EVP_EncryptFinal (ctx, TAG, &howmany);
  EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_GET_TAG, 16, TAG);  
  EVP_CIPHER_CTX_free(ctx);
  // Decrypt
  ctx = EVP_CIPHER_CTX_new();      
  EVP_DecryptInit (ctx, cipher, KEY, IV);
  EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_TAG, 16, ref_TAG);
  EVP_DecryptInit (ctx, NULL, KEY, IV);
  EVP_DecryptUpdate (ctx, NULL, &howmany, AAD, aad_len);
  len = 0;
  while(len <= in_len-128)
  {
     EVP_DecryptUpdate (ctx, decrypted_CT+len, &howmany, CIPHERTEXT+len, 128);
     len+=128;
  }
  EVP_DecryptUpdate (ctx, decrypted_CT+len, &howmany, CIPHERTEXT+len, in_len-len);
  dec_success = EVP_DecryptFinal (ctx, dec_TAG, &howmany);
  EVP_CIPHER_CTX_free(ctx);

最后您应该检查 dec_success 的值是否为 1。 如果您修改了 CIPHERTEXT,则在解密之前,您应该获得值 0。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 EVP 接口的 AES-GCM OpenSSL C 示例 的相关文章

  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • 动态生成的 Perl Moose 访问器

    请参阅以下基于 Moose 的 Perl 代码片段 BusinessClass gt meta gt add attribute Key gt is gt rorw isa gt MooseType lazy gt 0 required g
  • C语言中如何连接两个整数

    Stack Overflow 用许多其他语言回答了这个问题 但没有用 C 语言回答 所以我想我会问 因为我有同样的问题 C语言中如何连接两个整数 Example x 11 y 11 我想要 z 如下 z 1111 其他示例尝试使用字符串来执
  • N层架构中如何维护事务

    我正在 N 层架构中开发应用程序 众所周知 我们需要在插入 更新 删除操作时实现事务 请告诉我如何在 N 层架构的 c net 中使用事务 我的架构是这样的 Applicationform gt middle Layre gt Factor
  • simple_form 带有自定义包装器的自定义输入

    我正在尝试在我的应用程序中为货币进行自定义输入 我有那些 bootstrap 包装器等 我认为它带有 simple form 或 bootstrap gem 所以 我可以做类似的事情 它的工作原理正如预期的那样 问题是 我在很多地方都需要同
  • 登录框架

    想象一下有一个框架提供了一个名为logutils set up 它根据某些配置设置日志记录 应尽早设置日志记录 因为导入库期间发出的警告不应丢失 由于旧方法 if name main 看起来很难看 我们使用控制台脚本入口点来注册main m
  • 添加一些内容后的 VB.Net 双重比较

    在向双变量添加一些值后 我遇到了一个奇怪的情况 当将 0 2 多次添加到双精度变量时会出现问题 我认为这只发生在 0 2 例如 考虑以下代码 Dim i As Double 2 i i 0 2 MsgBox i 2 2 MsgBox i g
  • VS2010添加新文件抛出设置属性'System.Windows.ResourceDictionary.DeferrableContent'抛出异常

    在 Visual Studio 2010 中 当我右键单击一个项目并选择 添加新项目 时 光标闪烁一秒钟 但没有任何反应 如果我去文件 gt 新建 gt 文件 我得到 设置属性 System Windows ResourceDictiona
  • IgnoreReadOnlyRecommended 打开 Excel 工作簿时无法从 Python 运行

    我有一个 Excel 工作簿 需要以可写模式从 python 打开 工作簿设置为提示只读推荐 https support office com en us article Prompt to open a Microsoft Office
  • 条码扫描仪读取代码速度太慢

    我使用 codenameone codescanner 库来读取条形码 它使用第三方扫描仪 如果单独使用 则可以正常工作并且可以快速读取条形码 但是使用codenameone应用程序 同样的扫描仪速度太慢 大多数时候无法扫描 我已经在三星设
  • 使用 iTextSharp 在 PdfPCell 中自动调整图像大小

    我在 iTextSharp 库中的图像遇到一个奇怪的问题 我将图像添加到 PdfPCell 中 由于某种原因它被放大了 我怎样才能保持原来的大小 我虽然打印时图像是相同的 但图片上的差异在打印版本上是相同的 必须使用 ScaleXXX 手动
  • Silverlight NavigationService 始终为空

    我读到有些人遇到了这个问题 所以我想发布一个我在尝试处理这个问题时想到的 有点 优雅的解决方案 问题是当您在 Silverlight 中创建模板化页面时 ContentControls 没有父 Frame 的 NavigationServi
  • 单击时引导按钮显示蓝色轮廓

    我添加了这个 但单击按钮时仍然会出现蓝色轮廓 btn focus outline none 怎么去掉那个丑陋的东西 可能您的属性正在被覆盖 尝试附加 important与 active 一起添加到您的代码中 btn focus btn ac
  • 处理 .NET IDisposable 对象

    我用 C 工作 而且我对使用相当松懈using块来声明实现的对象IDisposable 显然你总是应该这样做 然而 我没有找到一种简单的方法来知道我何时犯了错误 Visual Studio 似乎没有以任何方式表明这一点 我只是错过了什么吗
  • Airflow 能否持续访问短期动态生成任务的元数据?

    我有一个 DAG 每当检测到文件时FileSensor 为每个文件生成任务以 1 将文件移动到暂存区域 2 触发单独的 DAG 来处理文件 FileSensor gt Move File1 gt TriggerDAG File1 gt Do
  • 在 CSS 中将标题放在 2 条水平线内

    I want to put an h3 heading between 2 pairs of horizontal line just like that 任何人都可以帮助我实现这个想法 在 html css 中 UPDATE 请问我该如何
  • Python:从文件中选择随机行,然后删除该行

    我是 Python 新手 因为我是通过 CodeAcademy 课程学习的 需要一些帮助来解决这个问题 我有一个文件 TestingDeleteLines txt 大约有 300 行文本 现在 我试图让它从该文件中随机打印 10 行 然后删
  • 我应该创建一个 DateRange 对象吗?

    我的一些域对象包含日期范围作为一对开始和结束日期属性 public class Period public DateTime EffectiveDate get set public DateTime ThroughDate get set
  • keycloak中的邮件内容可以修改吗?

    我是 Keycloak 的新手 我的项目使用 keycloak 作为身份验证服务器 目前我正在我的项目中开发用户维护 因此当使用 WEB API 在 keycloak 中创建新用户时 我想向新创建的用户发送一封电子邮件 表示欢迎使用该应用程
  • 如何从 Stripe 获取本地化错误消息

    我们的一位客户触发了 您的卡资金不足 刷卡时出错登记 我们稍后才会收取费用 并且我们无法显示有用的错误消息 因为我们没有针对此错误的本地化信息 虽然我的兄弟姐妹问题直接在 Stripe Elements 中显示 本地化 支付源注册错误 ht
  • 使用 EVP 接口的 AES-GCM OpenSSL C 示例

    对于AES GCM加密 解密 我尝试了这个 但是有问题 ctx EVP CIPHER CTX new Get the cipher cipher EVP aes 128 gcm define GCM IV 000000000000 defi