使用ARM的Neon技术实现SHA256算法加速

news2025/1/11 14:04:52

需求

假设一款Armv8-A架构的芯片,由于没有硬件密码算法引擎,如何实现对SHA256算法加速。

方案

Arm Neon 技术,一种⾼级 SIMD(Single Instruction Multiple Data,一条指令操作多个数据)架构扩展,Armv8‑A 和 Armv8-R 架构均支持 Neon 技术扩展。使用 Neon 技术有多种方法:

  • 支持 Neon 的开源库,例如 Arm Compute Library
  • 编译器的自动矢量化特性可以利用 Neon 技术自动优化你的代码
  • Neon intrinsics内建函数,编译器用相应的 Neon 指令进行了封装
  • 对于经验丰富的程序员来说,为了获得极佳的性能,手动编写 Neon 汇编也是一种方法

加密扩展CE(Cryptographic Extension)是 Neon 其中的一种指令集,用于实现AES加解密和SHA哈希的加速运算。加速SHA256算法的Neon指令包括如下四种:

指令 功能
SHA256H SHA256 hash update (part 1)
SHA256H2 SHA256 hash update (part 2)
SHA256SU0 SHA256 schedule update 0
SHA256SU1 SHA256 schedule update 1

这里我们采用 Neon intrinsics 实现 SHA256 算法的加速,SHA256 Intrinsics 指令如下:

SHA256 Intrinsics

本方案需要对SHA256算法原理,Neon技术等有一定的了解,详细可参考本公众号/博客的其他文章。

实现

sha256.h

SHA256算法需要实现分片哈希和一次性哈希的功能,包括如下函数:

函数 功能
sha256_starts SHA256开始,创建上下文
sha256_update SHA256更新,输入消息数据
sha256_finish SHA256结束,得到摘要值
sha256_compute 计算一块数据的SHA256摘要值

上面前三个函数是分片计算哈希,最后一个函数是一次性计算哈希。新建一个sha256.h文件,代码如下:

#ifndef _SHA256_H_
#define _SHA256_H_

#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C"{
   
#endif

struct sha256_ctx
{
   
    uint32_t total[2];		/* 处理过的数据长度 */
    uint32_t state[8];      /* 中间摘要状态 */
    uint8_t buffer[64];     /* 正在处理的数据块 */
};
typedef struct sha256_ctx sha256_ctx_t;

/**
 ***********************************************************************************************************************
 * @brief           starts a sha256 context
 *
 * @param[in]       ctx: the context
 *
 * @return          0: success, other: fail
 ***********************************************************************************************************************
 */
int sha256_starts(sha256_ctx_t *ctx);

/**
 ***********************************************************************************************************************
 * @brief           this function feeds an input buffer into an ongoing sha256 context
 *
 * @param[in]       ctx: the context
 * @param[in]       input: the buffer holding the input data
 * @param[in]       ilen: the length of the input data
 *
 * @return          0: success, other: fail
 ***********************************************************************************************************************
 */
int sha256_update(sha256_ctx_t *ctx, const uint8_t *input, size_t ilen);

/**
 ***********************************************************************************************************************
 * @brief           the finalization function
 *
 * @param[in]       ctx: the context
 * @param[out]      output: the buffer holding the output data
 *
 * @return          0: success, other: fail
 ***********************************************************************************************************************
 */
int sha256_finish(sha256_ctx_t *ctx, uint8_t output[32]);

/**
 ***********************************************************************************************************************
 * @brief           compute the sha256 checksum of a buffer
 *
 * @param[in]       input: the buffer holding the input data
 * @param[in]       ilen: the length of the input data
 * @param[out]      output: the buffer holding the output data
 *
 * @return          0: success, other: fail
 ***********************************************************************************************************************
 */
int sha256_compute(const uint8_t *input, size_t ilen, uint8_t output[32]);

#ifdef __cplusplus
}
#endif

#endif  /* _SHA256_H_ */

其中定义了一个sha256上下文结构体,用于分片哈希计算,参数如下:

  • total:记录处理过的数据长度
  • state:记录中间摘要状态值
  • buffer:存放正在处理的数据块

sha256.c

新建一个sha256.c文件,需要实现sha256.h中定义的四个函数。

sha256_starts

sha256_starts函数主要是创建上下文,并设置初始的哈希值。

int sha256_starts(sha256_ctx_t *ctx)
{
   
    memset(ctx, 0, sizeof(sha256_ctx_t));

    /* 清零 */
    ctx->total[0] = 0;
    ctx->total[1] = 0;
    /* 初始哈希值 */
    ctx->state[0] = 0x6a09e667;
    ctx->state[1] = 0xbb67ae85;
    ctx->state[2] = 0x3c6ef372;
    ctx->state[3] = 0xa54ff53a;
    ctx->state[4] = 0x510e527f;
    ctx->state[5] = 0x9b05688c;
    ctx->state[6] = 0x1f83d9ab;
    ctx->state[7] = 0x5be0cd19;

    return 0;
}

sha256_update

sha256_update函数主要是进行哈希更新计算,由于sha256内部每次处理512比特(64字节),因此需要保证每次哈希更新计算的长度为512比特的倍数。

int sha256_update(sha256_ctx_t *ctx, const uint8_t *input, size_t ilen)
{
   
    size_t fill;
    uint32_t left;
    size_t block_num;
    size_t block_len;

    if (ilen == 0) {
   
        return 0;
    }

    /* 上次剩余的消息长度 */
    left = ctx->total[0] & 0x3F;
    /* 需要填充fill长度消息,sha256每次处理512比特(即64字节) */
    fill = 64 - left;

    /* 更新已处理的消息长度 */
    ctx->total[0] += (uint32_t)ilen;
    ctx->total[0] &= 0xFFFFFFFF;
    /* 产生进位,total[1]+1 */
    if (ctx->total[0] < (uint32_t)ilen) {
   
        ctx->total[1]++;
    }

    /* 先处理上一次剩余消息 */
    if (left && ilen >= fill) {
   
        /* 拷贝fill长度消息,使其为64字节 */
        memcpy((void *)(ctx->buffer + left), input, fill);
        sha256_internal_process(ctx->state, ctx->buffer, 1);
        input += fill;
        ilen  -= fill;
        left = 0;
    }

    /* 再处理输入消息 */
    block_num = ilen >> 6;
    block_len = block_num << 6;
    if (block_num) {
   
        sha256_internal_process(ctx->state, input, block_num);
        input += block_len;
        ilen -= block_len;
    }

    /* 剩余消息小于64字节,暂存 */
    if (ilen > 0) {
   
        memcpy((void *)(ctx->buffer + left), input, ilen);
    }

    return 0;    
}
  • 首先进行消息长度处理,与本次输入的消息长度相加
  • 如果上次有消息数据未处理,先要拷贝填充至64字节,进行哈希计算
  • 然后对本次的剩余消息按块计算哈希
  • 最后如果本次最后一个块不足64字节,需要进行数据暂存

其中sha256_internal_process是sha256的核心部分,实现内部的哈希调度计算,实现见下一节。

sha256_finish

sha256_finish函数是完成哈希计算,得到消息的摘要值。

/* 双字->4字节,大端模式 */
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE( n, data, offset )                        \
{
                                                                    \
    ( data )[( offset )    ] = (uint8_t) ( (n) >> 24 );         \
    ( data )[( offset ) + 1] = (uint8_t) ( (n) >> 16 );         \
    ( data )[( offset ) + 2] = (uint8_t) ( (n) >> 8  );         \
    ( data )[( offset ) + 3] = (u

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1686624.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新鲜干货|「隐语城市行·成都站 x 蓉数大讲堂」硬核技术分享、多元场景实践、未来趋势洞察及前沿学术探秘

“隐语”是开源的可信隐私计算框架&#xff0c;内置 MPC、TEE、同态等多种密态计算虚拟设备供灵活选择&#xff0c;提供丰富的联邦学习算法和差分隐私机制 开源项目 github.com/secretflow gitee.com/secretflow 5月18日&#xff0c;「隐语城市行成都站 x 蓉数大讲堂」线下活…

JVM优化之使用Jstack命令查找JVM死锁

JVM优化之使用Jstack命令查找JVM死锁 示例代码 public class DeadLockDemo {private static Object lock1 new Object();private static Object lock2 new Object();public static void main(String[] args) {new Thread(() -> {synchronized (lock1) {try {System.out.p…

适用于 Windows 7/8/10/11 的 6 款最佳免费分区软件

分区软件程序旨在帮助您创建、缩小、删除、扩展、合并或拆分硬盘和其他存储设备的分区。虽然可以在 Windows 中对硬盘进行分区而无需使用其他软件&#xff0c;但您可以执行的活动范围有限。例如&#xff0c;如果没有外部工具&#xff0c;您无法调整分区大小或合并分区。在这篇文…

Less语言

Less是一门预编译语言&#xff0c;它扩展了CSS语言&#xff0c;增加了变量、Mixin、函数等特性&#xff0c;使CSS更易维护和扩展 Less也扩充了CSS语言&#xff0c;增加了诸如变量、混合运算、函数等功能。Less既可以运行在服务端(Node.js和Rhino平台)也可以运行在客户端(浏览器…

2024中青杯A题数学建模成品文章数据代码分享

人工智能视域下养老辅助系统的构建 摘要 随着全球人口老龄化的加剧&#xff0c;养老问题已经成为一个世界性的社会问题&#xff0c;对社会各个方面产生了深远影响&#xff0c;包括劳动力市场、医疗保健和养老金制度等。人口结构变化对养老服务的质量和覆盖面提出了更高要求。特…

go-zero 实战(3)

引入 Redis 在之前的 user 微服务中引入 redis。 1. 修改 user/internal/config/config.go package configimport ("github.com/zeromicro/go-zero/core/stores/cache""github.com/zeromicro/go-zero/zrpc" )type Config struct {zrpc.RpcServerConfMys…

SAP PRD覆盖QAS 替代方案构想

随着时间的推移&#xff0c;SAP PRD的数据跟QAS的差异会越来越大&#xff0c;一般是定期PRD覆盖QAS。但是在没有BASIS的情况下&#xff0c;没有这块经验的情况下&#xff0c;也没有外部支持的情况下&#xff0c;贸然做这个事情也是有风险的&#xff0c;有没有替代方案&#xff…

【ArcGIS微课1000例】0112:沿线(面)按距离或百分比生成点

文章目录 一、沿线生成点工具介绍二、线状案例三、面状案例一、沿线生成点工具介绍 位置:工具箱→数据管理工具→采样→沿线生成点 摘要:沿线或面以固定间隔或百分比创建点要素。 用法:输入要素的属性将保留在输出要素类中。向输出要素类添加新字段 ORIG_FID,并设置为输…

地理信息系统(GIS)软件开发

地理信息系统&#xff08;GIS&#xff09;软件开发是一项复杂且系统性很强的工程&#xff0c;涉及空间数据的采集、管理、分析和展示。以下是一个典型的GIS软件开发流程&#xff0c;包括各个步骤的详细说明。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#…

K8S二进制安装与部署

一、安装部署步骤 1.1 初始化配置 1.2 所有 node 节点部署docker引擎 1.3 准备cfssl证书生成工具 1.4 生成Etcd证书 1.5 部署 Master 组件 1.6 部署 Worker Node 组件 1.7 部署 CNI 网络组件-部署 flannel 1.8 部署 CoreDNS 1.9 master02 节点部署 1.10 负载均衡部署…

dll文件是什么?电脑丢失某个dll文件有什么解决办法

Dll文件是什么&#xff1f;这个文件在电脑中是什么样的地位&#xff1f;如果电脑提示丢失了某个dll文件那么有什么办的解决这个问题呢&#xff1f;如何将丢失的dll文件进行修复呢&#xff1f;今天这篇文章将按就来教大家几种修复丢失dll文件问题的方法。 DLL 文件&#xff0c;全…

【永洪BI】超链接

1. 概述 1.1 功能简介 超链接&#xff0c;是将不同内容进行连接的元素&#xff0c;可以在表、图表、文本等组件上设置超链接&#xff0c;在预览时可以查看超链接效果。 产品内的超链接包括&#xff1a;链接到报告、链接到指定网址、导出、刷新、数据。 1.2 应用场景 想要从…

【Python】 如何使用逗号作为千位分隔符打印数字

基本原理 在Python中&#xff0c;打印数字时自动添加千位分隔符可以提高数字的可读性&#xff0c;尤其是在处理大数字时。Python提供了多种方法来实现这一功能&#xff0c;包括使用内置的format()函数、f-string&#xff08;格式化字符串字面量&#xff09;以及locale模块。 …

AI绘图副业创收,热门擦边变现赛道怎么玩?网友:瑟瑟才是人类前进的动力!

大家好&#xff0c;我是设计师阿威 今天给大家介绍一个用 AI 搞擦边的变现赛道 而且可以说是0 成本变现的 现在真的越来越多的人都想 0 成本变现&#xff0c;那么 0 成本到底能不能变现&#xff0c;变现的上下限又是多少&#xff1f; 今天这个案例就可以很好的进行说明 可以…

K8S认证|CKA题库+答案| 5. 创建 Ingress

5 . 创建 Ingress 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Master node Worker node k8s master …

python从0开始学习(九)

前言 上一篇文章我们介绍了python中的序列类型和元组类型&#xff0c;本篇文章将接着往下将。 1、字典类型 字典类型是根据一个信息查找另一个信息的方式所构成的“键值对”&#xff0c;它表示索引用的键和对应的值构成的成对关系。它是一个可变数据类型&#xff0c;也就是说它…

Cython学习笔记和例程

Chapter2 &#xff1a;Compiling and Running Cython Code 编译运行Cython代码有好几种方式&#xff0c;没有必要全部掌握&#xff0c;可以根据需要选择合适的方式。这里例举了3种常见方式&#xff0c;基本也够用了。一般方法3创建setup.py是最基础的&#xff0c;自由度也最高…

java+Angular+Nginx+原生HTML+JS+CSS+Jquery融合B/S版电子病历系统云HIS系统源码

javaAngularNginx原生HTMLJSCSSJquery融合B/S版电子病历系统云HIS系统源码 Java版云HIS系统融合电子病历系统&#xff0c;是医学专用软件。医院通过电子病历以电子化方式记录患者就诊的信息&#xff0c;包括&#xff1a;首页、病程记录、检查检验结果、医嘱、手术记录、护理记录…

新手第一次做抖店,应该注意什么?知道这些技巧让你更快拿到结果

大家好&#xff0c;我是电商花花。 新手第一次刚开始接触抖音小店&#xff0c;都会担心自己做不好&#xff0c;操作不到位的想法&#xff0c;怕自己做店长时间不出单。 其实做店担心不出单是很正常的&#xff0c;但是只要我们掌握正确的做店方法和技巧也能很快就做好抖音小店…

文件包含漏洞--pikachu靶场

目录 文件包含 文件包含函数 文件包含漏洞原理 文件包含的分类 LFI-本地文件包含 RFI-远程文件包含 基于pikachu靶场练习 本地文件包含 远程文件包含 防御 文件包含 文件包含是程序员将需要重复调用的函数写入一个文件&#xff0c;对该文件包含时的操作&#xff0c;如…