透过 Delphi 使用二进位金钥做 AES 加密.
从 1994 年开始,笔者就开始接触加密与网路安全的世界,从鲁立忠老师的指导当中获益良多,后来在台湾的元智大学就读研究所的时候,也以此为研究主题。
在当时,电子商务是显学,Visa跟 Master Card还特别为了网路交易制作了厚厚三大本的商务通讯协定,命名为SET (Secure Electronic Transaction,安全电子交易),从客户端、商店端、银行端定义了绵绵密密的交易规范。
然而,网际网路的世界跟 Visa Master Card所熟悉的专用网路世界差的远了,不是大狗们(Big dogs)说了算,很快的 SSL 128 被吹捧成『最安全的交易保护机制』,每年透过这『最安全的交易保护机制』成交的金额越攀越高。
破解网路而得逞的网路诈欺,始终维持在一个很低的比例,反而从商家端流出的诈欺资料年年创新高,SET也很快的成为一个历史名词。
但是,SET所本的一些加密基础,并没有就此被埋没。X.509电子凭证、RC4, RC5, DES, 3-DES, RSA, SHA-1, SHA256, SHA-2, 还有我们这次要介绍的AES,也不断的推陈出新,在世界上蓬勃发展。这些听了令人打呵欠的主题跟名词,在很多地方都会被用上,只是用了不同的面貌呈现给使用者而已。
像是在台湾的自然人凭证、健保卡里面,都有个人电子凭证(X.509),每年五月我们在台湾都可以用这两种凭证进行网路报税。
或是像在台湾的电子发票,当中就需要用到 AES 加密,依据『纸本电子发票二维条码内容规范』第五页所述:

在纸本电子发票左方的二维条码里面,就需要用到 AES 对发票字轨10码及随机码4码以字串方式合并后使用AES加密,并采用Base64编码转换。
但是,在Delphi里面好像没有可以直接使用AES加密的单元可以使用。笔者在硕士论文的程式撰写时,使用的是OpenSSL 0.4的函式库,当时还叫做SSLeay呢。但是,这作法只能在Windows 平台上面顺顺的用,有没有什么方法可以让我们在不同的作业系统下都能顺利使用 AES 呢?
经过约莫两三个小时上穷碧落下黄泉的搜寻,找到了一个在 SourceForge 上面的加密范例程式,更棒的是,它是用 Delphi + FireMonkey 写的,不使用 DLL,而是使用纯粹的Pascal 写的 (感谢 Eldos 的 OpenSource, 但直接到 Eldos 网站的连结目前已经找不到了)。
换句话说,这是一个跨平台都可以正常运作的 Delphi 程式,不用依靠载入的 DLL 或 Lib,用这个范例来制作电子发票的验证加密字串,就能够很方便的达成了。
Source Forge 的范例程式可以从这个连结下载,下载之后,请看到里面的范例专案『FlyUtilsAESCBC.dproj』,这个范例程式中,支援用字串作为AES加密金钥(Key)对文字进行加解密,执行起来的画面也很清楚,笔者做了一点点修改,修改后的执行画面如下图所示:

左图是未执行加密作业前的画面,右图则是执行了加密作业之后的画面。原始的范例程式中,只支援完整的字串作为 AES 金钥,但我们常会用到二进位资讯来做金钥,这种情形下,金钥通常也会经过Base64编码过。
所以笔者稍微改写了一个function,新增了一个按钮,就是画面最底下的『AES加密with Byte Key』这个按钮的event handler。
如果点选按钮是 AES加密,则Key里面的字串不会被做任何处理,直接会被当成AES金钥,点选的如果是最底下的『AES加密with Byte Key』,则Key里面的字串会先被做Base64 解码,变成二进位资讯,AES金钥就是这些二进位资讯了。
procedure TFormMain.Button1Click(Sender: TObject);
var
KeyBit: TKeyBit;
APaddingMode: TPaddingMode;
begin
KeyBit := TKeyBit.kb256;
APaddingMode := TPaddingMode.pmZeroPadding;
Memo2.text := AESEncryptStrToBase64_Base64Key(Memo1.Text, Edit1.text, TEncoding.UTF8, KeyBit, '', APaddingMode, CheckBoxCBC.IsChecked,
rlCRLF, rlCRLF, Process);
end;
这儿的 AESEncryptStrToBase64_Base64Key 是笔者照着原本 Eldos 的程式做了一点小手脚,方便大家把电子发票平台取得的金钥直接贴上来就能用:
function AESEncryptStrToBase64_Base64Key(Value, Key: string; StrEncoding: TEncoding = nil;
KeyBit: TKeyBit = kb128;
InitVectorStr: string = '';
APaddingMode: TPaddingMode = TPaddingMode.pmPKCS5or7RandomPadding; CBCMode: Boolean = True;
ValueCRLFMode: TCRLFMode = rlCRLF;
KeyCRLFMode: TCRLFMode = rlCRLF;
OnProcessProc: TOnProcessProc = nil; ProcessProc: TProcessProc = nil): string;
var
tStrm : TBytesStream;
keyBytes: TBytes;
IVBytes: TBytes;
IdDecoderMIME1 : TIdDecoderMIME;
begin
tStrm := TBytesStream.create;
IdDecoderMIME1 := TIdDecoderMIME.Create(nil);
try
IdDecoderMIME1.DecodeBegin(tStrm);
IdDecoderMIME1.Decode(Key);
IdDecoderMIME1.DecodeEnd; keyBytes := tStrm.Bytes;
finally
tStrm.Free;
end; tStrm := TBytesStream.create;
try
IdDecoderMIME1.DecodeBegin(tStrm);
IdDecoderMIME1.Decode(InitVectorStr);
IdDecoderMIME1.DecodeEnd; IVBytes := tStrm.Bytes;
finally
tStrm.Free;
end;
IdDecoderMIME1.Free; Result := EncodeBase64Bytes(AESEncryptStr_BytesKey(Value, keyBytes, IVBytes, TEncoding.UTF8, KeyBit, APaddingMode, CBCMode, ValueCRLFMode,
KeyCRLFMode, OnProcessProc, ProcessProc));
end;
单独使用这个 function 的话,ProcessProc 参数可以给 nil, 这是用来让大家看到有进度列可以显示处理进度用的,通常这些处理是在背景进行,没有介面的时候直接给个 nil, 就可以不用管进度条了。
大家可以看到,上面的程式码里面,笔者使用了Indy的 Base64解码元件『IdDecoderMIME』,因为一来它是原本 Delphi 安装就内建的,使用上比较方便,二来笔者也熟悉这套元件,所以不另外找其他元件了。
AES 里面除了 Key 之外,还可以指定 IV (initialization vector), 如果使用上需要使用二进位的 IV, 您可以把二进位的 IV 先做好 Base64 编码,这个 function 也会将它先做 Base64 解码之后,作为 IV 进行处理的。
写到这里,说明的差不多了,范例程式专案我也准备好了,有兴趣的读者请自行取用吧。范例在此。
透过 Delphi 使用二进位金钥做 AES 加密.的更多相关文章
- 使用php扩展mcrypt实现AES加密
AES(Advanced Encryption Standard,高级加密标准)是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.Rijndael是 ...
- 【5】JMicro其于RSA及AES加密实现安全服务调用
JMicro是基于Java实现的微服务平台,最近花了两个周未实现服务间安全调用支持. JMicro服务调用分两个部份,分别为内部服务间相互调用和外部客户端通过API网关调用JMicro集群内部服务,前 ...
- [Java 实现AES加密解密]
今天同学请教我这个问题,被坑了次…… 实现的功能是2个Java类:一个读取源文件生成加密文件,另一个类读取加密文件来解密. 整个过程其实很简单,java有AES的工具包,设好秘钥,设好输入内容,就得到 ...
- ruby AES加密解密
最近和京东合作做一个项目,在接口对接传递参数时,参数需要通过AES加密解密. 本来想到用gem 'aescrypt'处理,但是aescrypt的编码方式用的base64,而京东那边用的是16进制.所以 ...
- 【Python】 基于秘钥的对称加密
[Crypto] 关于用python进行信息的加密,类似的解决方案有很多比如用base64编码进行encode,再或者是hashlib来进行hash.但是还缺少一种明明场景很简单的解决方案,就是把利用 ...
- java与C#、.NET AES加密、解密 解决方案
1.情景展示 Java提供的密钥,C#无法解密. 2.原因分析 在Java中,AES的实际密钥需要用到KeyGenerator 和 SecureRandom,但是C#和.NET 里面没有这2个类, ...
- 你真的了解字典(Dictionary)吗? C# Memory Cache 踩坑记录 .net 泛型 结构化CSS设计思维 WinForm POST上传与后台接收 高效实用的.NET开源项目 .net 笔试面试总结(3) .net 笔试面试总结(2) 依赖注入 C# RSA 加密 C#与Java AES 加密解密
你真的了解字典(Dictionary)吗? 从一道亲身经历的面试题说起 半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点.为了便于描述,我把上面 ...
- 使用Python进行AES加密和解密
摘录于:http://blog.csdn.net/nurke/article/details/77267081 另外参考:http://www.cnblogs.com/kaituorensheng/p ...
- AES加密、解密工具类
AES加密.解密工具类代码如下: package com.util; import java.io.IOException; import java.io.UnsupportedEncodingExc ...
随机推荐
- juddi学习一
一.下载juddi 地址:https://mirrors.tuna.tsinghua.edu.cn/apache/juddi/juddi/3.3.4/ 二. 解压下载文件打开目录下的 进入bin目录, ...
- ajax VS websocket
一. ajax VS websocket总结 http://blog.csdn.net/qiuhuanmin/article/details/50719114 二.用Websocket代替Ajax来开 ...
- 老李分享:SSL协议相关证书
老李分享:SSL协议相关证书 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:9088214 ...
- POPTEST老李谈JVM、JRE、JDK、java ee sdk with jdk区别
POPTEST老李谈JVM.JRE.JDK.java ee sdk with jdk区别 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等 ...
- Learning to Rank简介
Learning to Rank是采用机器学习算法,通过训练模型来解决排序问题,在Information Retrieval,Natural Language Processing,Data Mini ...
- 高性能MySQL--索引学习笔记(原创)
看过一些人写的学习笔记,完全按书一字不漏照抄,内容很多,真不能叫笔记.遂自己整理了一份,取其精要. 更多笔记请访问@个人简书 [toc] 索引概述 索引即key 在存储引擎层实现,不同引擎工作方式不同 ...
- a标签传值乱码问题怎么解?
- Python 安装虚拟环境
写在前面: 安装指南是在 Ubuntu 下面操作的.不同的 Linux 版本,安装指令不同.所以,该指南的某些指令对于像 CentOS 等非 Ubuntu 系统不适用. 为什么需要使用虚拟环境? 虚拟 ...
- python黑魔法之metaclass
最近了解了一下python的metaclass,在学习的过程中,把自己对metaclass的理解写出来和大家分享. 首先, metaclass 中文叫元类,这个元类怎么来理解呢.我们知道,在Pytho ...
- 深入理解css中vertical-align属性
一.为什么要写这篇文章 今天看到一个问题: 两个div 都设置 display:inline-block,正常显示:但是在第二个div中加一个块级元素或者内联元素,显示就变了个样,为什么? <m ...