Delphi是一种通过使用Object Pascal快速开发本机Windows,macOS,Linux,iOS和Android应用程序的语言。该名称是指Delphi语言及其库,编译器和IDE,用于帮助编辑和调试Delphi项目。
Delphi XE5 FireDAC 错误:无法加载供应商库 [libmysql.dll 或 libmysqld.dll]
我在 Windows 7 64 位上使用 Delphi XE5,只是尝试 FireDAC 组件。 我正在使用一个 TFDConnection 组件连接到本地 MySQL 数据库 (v5.6.15)。 我已经把libmysql.dll(32位...
如何使用 IEnumerator、IEnumerable 接口编写 COM 对象
我正在尝试用Delphi中的Enumerable和Enumerator编写一个COM对象。这是一场噩梦。 首先在 .ridl 文件中: 接下来在 _tlb.pas 中我有这个: //****************************...
将下一个控件聚焦在 Enter 上 - 在覆盖的 KeyUp 中
我有扩展 TEdit 的自定义类: TMyTextEdit = 类 (TEdit) 私人的 fFocusNextOnEnter: 布尔值; 民众 procedure KeyUp(var Key: Word; Shift :TShiftState);覆盖;
我是Delphi新手,但我需要修复Delphi代码,以便在执行“服务启动”时挂载网络磁盘。默认情况下,当我的应用程序由 Windows Se 启动时...
使用 Delphi 10.4 和 OmniThreadLibrary 高效处理大量 API 调用
我正在寻找有关如何使用 Delphi 10.4 和 OmniThreadLibrary 有效处理大量 API 调用的指南。 具体来说,我需要对
我正在尝试向应用程序动态添加按钮控件。我正在开发的应用程序有多达 6 个不同的预定义按钮位置,可以是几种不同操作中的任何一种...
如何在Delphi中的自己的窗口(表单,画布)中启动屏幕保护程序?
我使用将我的电脑镜像到电视的软件。效果很好,但传输屏保时会崩溃。 其中一个屏幕保护程序提供了在自己的窗口中启动它的选项 - 因此
如何在 Vue.js 中调用 SOAP Web 服务器方法?
我用Delphi开发了一个小型独立网络服务器。程序如下: 函数 sum(a,b:string):string;stdcall; 开始 结果:=a+b; 结尾; 我如何在 Vue JS 中调用它? Web 服务 URL 我...
如何在Delphi TMonthCalendar中本地化“今天”?
我对 Windows 和 Delphi 2007 上的默认月历控件有疑问。 默认情况下,我的开发环境是法语。 我需要将这些文本翻译成佛兰芒语 (nl-BE)。不用担心,我...
Delphi TClientDataSet.IndexFieldNames 真的从数据集中删除记录(使它们不可见)吗?
我在Delphi中执行以下代码: MyClientDataSet.IndexFieldNames:='FIELD1;FIELD2;FIELD3' 我可以看到 MyClientDataSet.RecordCount 显示记录数量减少,而这个临时...
我使用 teechart pro vcl 根据输入数据绘制图表。 我从 comport 读取数据并使用以下代码将点添加到 TFastlineseries : 变量 a:整数; b:双; ---------------------------- W...
我正在使用delphi,当我执行openpicturedialog时,我想要一个目录中所有文件的列表。 即,当执行打开对话框时并且 我从中选择一个文件,我想要 列表...
我的IDE是Delphi 10.3。 我有一个 Firebird 2.5 表,附件字段类型是 Binary Blob。我可以打开此存储的文件(图像、word、excel、pdf、txt...)而不保存到磁盘吗? 如果这不是
Delphi (FMX):Windows 中的 DCPCrypt2 在 Android/IOS 中产生不同的结果
我正在尝试编写一个函数,该函数在 Delphi (RAD Studio 10.2) 中返回与 PHP 中的以下代码相同的结果: 我正在尝试编写一个在 Delphi (RAD Studio 10.2) 中返回与 PHP 中的以下代码相同的结果的函数: <?php $method = 'AES-256-CTR'; $data = 'Hello, world!'; $key = 'bRuD5WYw5wd0rdHR9yLlM6wt2vteuini'; $vector = 'bf49ea9d61104d8c'; $crypt = openssl_encrypt($data, $method, $key, 0, $vector); echo $crypt; ?> 我在 Pascal 中提出了这个函数(使用 David Barton 编写的 DCPcrypt v2.1 库): procedure TMainForm.Encrypt1ButtonClick(Sender: TObject); var Cipher: TDCP_rijndael; Key, Vector: RawByteString; Data, Crypt: RawByteString; begin Data := 'Hello, world!'; SetLength(Crypt, Length(Data)); Key := 'bRuD5WYw5wd0rdHR9yLlM6wt2vteuini'; Vector := 'bf49ea9d61104d8c'; Cipher := TDCP_rijndael.Create(nil); try Cipher.Init(Key[1], 256, @Vector[1]); Cipher.EncryptCTR(Data[1], Crypt[1], Length(Data)); finally Cipher.Free; end; EncryptEdit.Text := DCPBase64.Base64EncodeStr(Crypt); end; 这确实有效(在 Windows 中)。 PHP 和 Pascal 都返回:pEP16OOxov9QDfraIg== 但是,如果我为 Android 编译相同的代码并在平板电脑上运行它,我会得到非常不同的结果。这是为什么? 我确实阅读了有关转换 fmx 代码的文档,特别是处理字符串处理的内容,但我仍然不明白为什么。即使 RawByteString 是基于 0 而不是基于 1,我仍然会得到差异(尝试使用 [0] 而不是 [1])。 RawByteString 没有附加代码页,对吧?所以这个问题不可能是由某些字符串转换引起的(我认为)。那么这是怎么回事? 经过3天的努力,我终于成功了。关键是完全消除字符串的使用,并且仅使用 DCPCrypt 中基于 TByte 的例程。 下面的代码是一个测试程序,用于测试 DCPCrypt 支持的所有不同链接模式。我还添加了一个函数来实现我在这里找到的四种填充模式(与 CBC 和 ECB 一起使用): https://en.wikipedia.org/wiki/Padding_(密码学) 以及零填充和随机填充。 我选择不使用 DCPCrypt 自己的 Base64 函数,因为它们与 FMX 不兼容。相反,我使用 System.NetEncoding 单元中的对应项。 拜托,我认为自己只是一个普通的程序员,所以我希望你们当中真正的 Delphi 奇才能够找到很多可以批评的地方。但没关系。如果给出良好的反馈,我将调整代码。 现在,代码可以运行并生成与 PHP 的 openssl 函数兼容的结果(使用 CTR 模式进行测试)。我只是在这里发布此内容,希望它对寻找与我相同的解决方案的人有用。 unit MainUnit; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.NetEncoding, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, FMX.Layouts, FMX.ScrollBox, FMX.Memo, FMX.Edit, FMX.Controls.Presentation, DCPcrypt2, DCPsha256, DCPblockciphers, DCPrijndael; type TChainingMode = (cmCBC, cmCFB8bit, cmCFBblock, cmOFB, cmCTR, cmECB); TPaddingMode = (pmZeroPadding, pmANSIX923, pmISO10126, pmISO7816, pmPKCS7, pmRandomPadding); type TMainForm = class(TForm) ScrollBox: TScrollBox; KeySizeLabel: TLabel; ChainingLabel: TLabel; EncodingLabel: TLabel; PaddingLabel: TLabel; KeyLabel: TLabel; InitVectorLabel: TLabel; DataLabel: TLabel; DecryptedLabel: TLabel; CipherLabel: TLabel; EncryptedLabel: TLabel; rbRijndael: TRadioButton; rb128bit: TRadioButton; rb256bit: TRadioButton; rbANSI: TRadioButton; rbUTF8: TRadioButton; rbUnicode: TRadioButton; rbCBC: TRadioButton; rbOFB: TRadioButton; rbCTR: TRadioButton; rbECB: TRadioButton; rbCFB8bit: TRadioButton; rbCFBblock: TRadioButton; rbZeroPadding: TRadioButton; rbANSIX923: TRadioButton; rbISO10126: TRadioButton; rbISO7816: TRadioButton; rbPKCS7: TRadioButton; rbRandomPadding: TRadioButton; KeyEdit: TEdit; InitVectorEdit: TEdit; DataMemo: TMemo; EncryptedMemo: TMemo; DecryptedMemo: TMemo; EncryptButton: TButton; DecryptButton: TButton; procedure FormCreate(Sender: TObject); procedure EncryptButtonClick(Sender: TObject); procedure DecryptButtonClick(Sender: TObject); public procedure GetOptions(var Key: TBytes; var KeySize: integer; var InitVector: TBytes; var Encoding: TEncoding; var ChainingMode: TChainingMode; var PaddingMode: TPaddingMode); end; var MainForm: TMainForm; implementation {$R *.fmx} {$R *.LgXhdpiPh.fmx ANDROID} function BytesToHex(B: TBytes): string; var I: integer; begin Result := ''; for I := Low(B) to High(B) do Result := Result + IntToHex(B[I]) + ' '; end; procedure BytePadding(var Data: TBytes; BlockSize: integer; PaddingMode: TPaddingMode); // Supports: ANSI X.923, ISO 10126, ISO 7816, PKCS7, zero padding and random padding var I, DataBlocks, DataLength, PaddingStart, PaddingCount: integer; begin BlockSize := BlockSize div 8; // convert bits to bytes // Zero and Random padding do not use end-markers, so if Length(Data) is a multiple of BlockSize, no padding is needed if PaddingMode in [pmZeroPadding, pmRandomPadding] then if Length(Data) mod BlockSize = 0 then Exit; DataBlocks := (Length(Data) div BlockSize) + 1; DataLength := DataBlocks * BlockSize; PaddingCount := DataLength - Length(Data); // ANSIX923, ISO10126 and PKCS7 store the padding length in a 1 byte end-marker, so any padding length > $FF is not supported if PaddingMode in [pmANSIX923, pmISO10126, pmPKCS7] then if PaddingCount > $FF then Exit; PaddingStart := Length(Data); SetLength(Data, DataLength); case PaddingMode of pmZeroPadding, pmANSIX923, pmISO7816: // fill with $00 bytes FillChar(Data[PaddingStart], PaddingCount, 0); pmPKCS7: // fill with PaddingCount bytes FillChar(Data[PaddingStart], PaddingCount, PaddingCount); pmRandomPadding, pmISO10126: // fill with random bytes for I := PaddingStart to DataLength-1 do Data[I] := Random($FF); end; case PaddingMode of pmANSIX923, pmISO10126: Data[DataLength-1] := PaddingCount; // set end-marker with number of bytes added pmISO7816: Data[PaddingStart] := $80; // set fixed end-markder $80 end; end; procedure EncryptAES(const Data: TBytes; var Crypt: TBytes; const Key: TBytes; KeySize: integer; const InitVector: TBytes; ChainingMode: TChainingMode; PaddingMode: TPaddingMode); overload; var Cipher: TDCP_rijndael; begin Cipher := TDCP_rijndael.Create(nil); try Cipher.Init(Key[0], KeySize, @InitVector[0]); // Copy Data => Crypt Crypt := Copy(Data, 0, Length(Data)); // Padd Crypt to required length (for Block based algorithms) if ChainingMode in [cmCBC, cmECB] then BytePadding(Crypt, Cipher.BlockSize, PaddingMode); // Encrypt Crypt using the algorithm specified in ChainingMode case ChainingMode of cmCBC: Cipher.EncryptCBC(Crypt[0], Crypt[0], Length(Crypt)); cmCFB8bit: Cipher.EncryptCFB8bit(Crypt[0], Crypt[0], Length(Crypt)); cmCFBblock: Cipher.EncryptCFBblock(Crypt[0], Crypt[0], Length(Crypt)); cmOFB: Cipher.EncryptOFB(Crypt[0], Crypt[0], Length(Crypt)); cmCTR: Cipher.EncryptCTR(Crypt[0], Crypt[0], Length(Crypt)); cmECB: Cipher.EncryptECB(Crypt[0], Crypt[0]); end; finally Cipher.Free; end; end; procedure DecryptAES(const Crypt: TBytes; var Data: TBytes; const Key: TBytes; KeySize: integer; const InitVector: TBytes; ChainingMode: TChainingMode; PaddingMode: TPaddingMode); overload; var Cipher: TDCP_rijndael; I: integer; begin Cipher := TDCP_rijndael.Create(nil); try Cipher.Init(Key[0], KeySize, @InitVector[0]); // Copy Crypt => Data Data := Copy(Crypt, 0, Length(Crypt)); // Decrypt Data using the algorithm specified in ChainingMode case ChainingMode of cmCBC: Cipher.DecryptCBC(Data[0], Data[0], Length(Data)); cmCFB8bit: Cipher.DecryptCFB8bit(Data[0], Data[0], Length(Data)); cmCFBblock: Cipher.DecryptCFBblock(Data[0], Data[0], Length(Data)); cmOFB: Cipher.DecryptOFB(Data[0], Data[0], Length(Data)); cmCTR: Cipher.DecryptCTR(Data[0], Data[0], Length(Data)); cmECB: Cipher.DecryptECB(Data[0], Data[0]); end; // Correct the length of Data, based on the used PaddingMode (only for Block based algorithms) if ChainingMode in [cmCBC, cmECB] then case PaddingMode of pmANSIX923, pmISO10126, pmPKCS7: // these modes store the original Padding count in the last byte SetLength(Data, Length(Data) - Data[Length(Data)-1]); pmISO7816: // this mode uses a fixed end-marker. Find it and correct length accordingly. for I := Length(Data)-1 downto 0 do if Data[I] = $80 then begin SetLength(Data, I); Break; end; end; finally Cipher.Free; end; end; procedure TMainForm.FormCreate(Sender: TObject); begin EncryptedMemo.Lines.Clear; DecryptedMemo.Lines.Clear; end; procedure TMainForm.GetOptions(var Key: TBytes; var KeySize: integer; var InitVector: TBytes; var Encoding: TEncoding; var ChainingMode: TChainingMode; var PaddingMode: TPaddingMode); begin KeySize := 256; Encoding := TEncoding.ANSI; ChainingMode := cmCBC; PaddingMode := pmPKCS7; if rb128bit.IsChecked then KeySize := 128; if rb256bit.IsChecked then KeySize := 256; if rbCBC.IsChecked then ChainingMode := cmCBC; if rbCFB8bit.IsChecked then ChainingMode := cmCFB8bit; if rbCFBblock.IsChecked then ChainingMode := cmCFBblock; if rbOFB.IsChecked then ChainingMode := cmOFB; if rbCTR.IsChecked then ChainingMode := cmCTR; if rbECB.IsChecked then ChainingMode := cmECB; if rbZeroPadding.IsChecked then PaddingMode := pmZeroPadding; if rbANSIX923.IsChecked then PaddingMode := pmANSIX923; if rbISO10126.IsChecked then PaddingMode := pmISO10126; if rbISO7816.IsChecked then PaddingMode := pmISO7816; if rbPKCS7.IsChecked then PaddingMode := pmPKCS7; if rbRandomPadding.IsChecked then PaddingMode := pmRandomPadding; if rbANSI.IsChecked then Encoding := TEncoding.ANSI; if rbUTF8.IsChecked then Encoding := TEncoding.UTF8; if rbUnicode.IsChecked then Encoding := TEncoding.Unicode; Key := Encoding.GetBytes(KeyEdit.Text); InitVector := Encoding.GetBytes(InitVectorEdit.Text); end; procedure TMainForm.EncryptButtonClick(Sender: TObject); var Keysize: integer; Encoding: TEncoding; ChainingMode: TChainingMode; PaddingMode: TPaddingMode; Key, InitVector, Data, Crypt: TBytes; begin GetOptions(Key, KeySize, InitVector, Encoding, ChainingMode, PaddingMode); Data := Encoding.GetBytes(DataMemo.Text); EncryptAES(Data, Crypt, Key, KeySize, InitVector, ChainingMode, PaddingMode); EncryptedMemo.Text := TNetEncoding.Base64.EncodeBytesToString(Crypt); end; procedure TMainForm.DecryptButtonClick(Sender: TObject); var Keysize: integer; Encoding: TEncoding; ChainingMode: TChainingMode; PaddingMode: TPaddingMode; Key, InitVector, Data, Crypt: TBytes; begin GetOptions(Key, KeySize, InitVector, Encoding, ChainingMode, PaddingMode); Crypt := TNetEncoding.Base64.DecodeStringToBytes(EncryptedMemo.Text); DecryptAES(Crypt, Data, Key, KeySize, InitVector, ChainingMode, PaddingMode); DecryptedMemo.Text := Encoding.GetString(Data); end; end. Android 字符串从位置 0 开始。您可以使用 low(Data) 返回字符串的第一个字符,库内部也使用从位置 1 开始的字符串,这不会在 android 或 ios 中运行。对于多平台,我们不应该使用 for i:=1 to length(string) 而应该使用 for l in string 我认为LockBox3应该可以解决你的问题。 我在这里面临着同样的问题,并且想运行您测试应用程序。能提供一下fmx表格的源码吗? 非常感谢!
如何使用 Delphi 将各种文档类型添加到 Firebird BLOB 字段
背景:我们的产品包括一个文档管理系统,允许用户保存和检索各种文档类型(.PDF、.DOC、.JPG、.PNG、.TIF 等)。目前
使用 mongo-delphi-driver 获取具有特定 _id 的文档
我必须在mongodb上执行查询,我想仅选择具有特定_id(类型ObjectId)的文档。 我使用“严格模式”语法,特别是运算符 $oid 将 _id 与
我想使用 doxygen + pas2dox 记录我的源代码。当我设置好所有内容(包括过滤器和提取选项(提取所有内容))时,doxygen 运行良好。但是生成的文档...
如何使用 Delphi 10(西雅图)在 Excel 中合并 2 个单元格
互联网上曾经有很多Delphi参考资料。我尝试用谷歌搜索,我从黛博拉·佩特 (Deborah Pate) 那里获得的 com 编程的首选现在给了我一个 404 页面未找到!不好了! 无论如何,我正在使用...
如何在 Delphi 中将带有图像的 RichText (RTF) 文档转换为 HTML?
我一直在尝试找到一个免费的(最好是开源的)组件或库,它可以将嵌入图像的 RTF 文件转换为 HTML 文件和图像文件或更好的 HTML 和图像
当最大化表单时(即使在 IDE 设计器中),Delphi 表单会出现不正确的行为,为什么?
这是完整 Delphi 应用程序的精简版本。 即使在Delphi7 IDE设计器中,当双击窗体的标题时,窗体也会错误地最大化,这意味着左上角