透过 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 ...
随机推荐
- 老李分享:Web Services 架构 2
服务传输层 这一层负责应用之间的消息传输.目前,该层包括了超文本传输协议(HTTP).简单邮件传输协议(SMTP).文件传输协议(FTP).以及一些新兴协议,比如块可扩展交换协议(BEEP). XML ...
- 关于android混淆文件project.properties和proguard-project.txt详解
一直不明白Android开发中的有些文件的具体作用,后来用到了,具体研究了一下,借鉴了一下网上的资料,最后总结下,方便以后查看! 老版本中有这么个文件default.properties,既然是老版本 ...
- JavaScript编码解码以及C#中的编码解码
JS: 编码 解码 escape unescape encodeURI decodeURI encodeURIComponent decodeURIComponent C#: HttpUtilit ...
- 使用JSONObject生成和解析json
1. json数据类型 类型 描述 Number 数字型 String 字符串型 Boolean 布尔型 Array 数组,以"[]"括起来 Object 对象,类似于C中的结构体 ...
- lua 数组
lua 数组 语法结构 arr = { - } 一维数组 数组的值仍然是数组的, 为多维数组, 否则为一维数组 示例程序 local arr = {1, 2, 3} for i = 1, #arr d ...
- sizeof 与 strlen
一.sizeof sizeof(...)是运算符,其值在编译时即计算好了,参数可以是数组.指针.类型.对象.函数等. 它的功能是:获得保证能容纳实现所建立的最大对象的字节大小. 由 ...
- Java--定时器问题
定时器问题 定时器属于基本的基础组件,不管是用户空间的程序开发,还是内核空间的程序开发,很多时候都需要有定时器作为基础组件的支持.一个定时器的实现需要具备以下四种基本行为:添加定时器.取消定时器.定时 ...
- JS理解之闭包
首先,闭包是什么?这个问题,百度上一大堆,然后我也是,现在学的有点累,来回顾一下吧算是,懂的自动略过,小弟不才,道行入不了你们法眼. 我认为的闭包是,就是取到,不是在自己作用域内或者按照js的规则,娶 ...
- Python之路- 反射&定制自己的数据类型
一.isinstance和issubclass isinstance(obj,cls)检查是否obj是否是类 cls 的对象 issubclass(sub, super)检查sub类是否是 super ...
- Amazon Alexa登录授权(Android)
访问Alexa的API,必须要携带AccessToken,也就是必须要登录授权,本文主要记录Amazon Alexa在Android平台上的登录授权过程. 一.在亚马逊开发者平台注册应用 进入亚马逊开 ...