[Delphi]一个功能完备的国密SM4类(TSM4)[20230413更新]

国密SM4加解密SM2签名验签COM组件DLL 提供给第三方软件,调用COM组件DLL方式进行实现,如delphi、PB等。 基于C#编写的COM组件DLL,可实现SM2签名验签,SM4加解密,100%适用于黑龙江省国家医保接口中进行应用。 功能包括:国密SM4加密、SM4解密、SM2签名、SM2验签(有需要可联系加入) 1、调用DLL名称:JQSM2SM4.dll 加解密类名:JQSM2SM4.SM2SM4Util CLSID=5B38DCB3-038C-4992-9FA3-1D697474FC70 2、GetSM2SM4函数说明 函数原型p. 阅读详情

【本软件可以到http://bbs.2ccc.com/topic.asp?topicid=673698的31楼直接下载】

本软件使用Delphi 10.3.3编写和测试, 源码中用到了System.NetEncoding和Generics.Collections两个单元, 因此本程序仅支持Delphi XE及更新的版本.

支持6种加密模式: ECB, CBC, CFB, OFB, PCBC, CTR; 默认为ECB;

支持7种填充模式(ZERO, PKCS5, PKCS7, ISO10126, ANSIX923, OneAndZero); 默认为PKCS7;

SM4要求密码长度的长度为16个字节(128bit), 如果长度不足, 程序就填充0x00来补足

SM4要求初始向量的长度为16个字节(128bit), 如果长度不足, 程序就填充0x00来补足

SrcBuffer, KeyBuffer, IVBuffer, DestBuffer: TBuffer 说明:

SrcBuffer存放待加密/解密的数据,

KeyBuffer存放密码数据,

IVBuffer存放初始向量数据,

DestBuffer存放已加密/解密的数据

TBuffer本身带有各种数据转换函数, 数据转换非常方便,不需要另外再写代码,例如:

function ToString: String;

function ToString(Encoding: TEncoding): String;

function ToHexString: String;

function ToDelimitedHexString(Prefix: String; Delimitor: String): String;

function ToBase64String: String;

procedure ToBytes(var Dest; Len: Integer); overload;

procedure FromString(const Str: String);

procedure FromString(const Str: String; Encoding: TEncoding);

procedure FromHexString(const Str: String);

procedure FromDelimitedHexString(HexStr: String; Prefix: String; Delimitor: String');

procedure FromBase64String(const Str: String);

procedure FromBytes(const Source; Len: Integer); overload;

最简单的TSM4使用示范代码:


//最简单的使用示范
procedure TMainForm.Test;
var
  S1, S2: String;
begin
  with TSM4.Create(cmCBC, pmPKCS5) do
  begin
    SrcBuffer.FromString('先学着让自己值钱');
    KeyBuffer.FromBase64String('MTIzNDU2Nzg5MDEyMzQ1Ng=='); //1234567890123456
//或KeyBuffer.FromString('1234567890123456');
    IVBuffer.FromHexString('6162636465666768696A6B6C6D6E6F70'); //abcdefghijklmnop
    Encrypt;  //加密
    S1 := DestBuffer.ToHexString; //6C19FEC30147DBDE9539DC1DF0F3ACF09B6E6210F0F220D3D923F200DC5A44C4
    
    SrcBuffer.FromHexString(S1);
    Decrypt;  //解密
    S2 := DestBuffer.ToString; //'先学着让自己值钱'
    Free;
  end;
end;

完整的TSM4代码(包括测试代码)


unit uMain;

interface

uses
{$IF CompilerVersion <= 22}
  Windows, Messages, Generics.Collections, SysUtils,
  Variants, Classes, Graphics, Controls, Forms,
  Dialogs, NetEncoding, StdCtrls, uSM4;
{$ELSE}
  Winapi.Windows, Winapi.Messages, Generics.Collections, System.SysUtils,
  System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
  Vcl.Dialogs, System.NetEncoding, Vcl.StdCtrls, uSM4;
{$ENDIF}

type
  TMainForm = class(TForm)
    LabelBlockMode: TLabel;
    LabelPaddingmode: TLabel;
    ComboBoxCipherMode: TComboBox;
    ComboBoxPaddingmode: TComboBox;
    LabelStr: TLabel;
    LabelIV: TLabel;
    LabelEnc: TLabel;
    LabelDec: TLabel;
    EditKey: TEdit;
    EditIV : TEdit;
    EditDec: TEdit;
    EditEnc: TEdit;
    EditStr: TEdit;
    LabelKey: TLabel;
    ButtonEncrypt: TButton;
    ButtonDecrypt: TButton;
    ComboBoxStr: TComboBox;
    ComboBoxKey: TComboBox;
    ComboBoxIV: TComboBox;
    ComboBoxEnc: TComboBox;
    ComboBoxDec: TComboBox;
    LabelStrCnt: TLabel;
    LabelKeyCnt: TLabel;
    LabelIVCnt : TLabel;
    LabelEncCnt: TLabel;
    LabelDecCnt: TLabel;
    EditSrc: TEdit;
    ButtonToHex: TButton;
    ButtonToBase64: TButton;
    EditDest: TEdit;
    RzEdit1: TEdit;
    Label1: TLabel;
    ButtonFromHex: TButton;
    ButtonFramBase64: TButton;
    Label2: TLabel;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure EditChange(Sender: TObject);
    procedure ButtonClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ButtonConvertClick(Sender: TObject);
    procedure ButtonFromClick(Sender: TObject);
  private type
    TProc = procedure(const S: String) of object;
    Tfunc = function(): String of object;
    TFromDict = TDictionary<String, TProc>;
    TToDict   = TDictionary<String, TFunc>;
    TCountDict = TDictionary<TEdit, TLabel>;
  private
    DIctCm: TDictionary<String, TCipherMode>;
    DIctPm: TDictionary<String, TPaddingMode>;
    DictFromStr, DictFromKey, DictFromIV, DictFromEnc: TFromDict;
    DictToEnc, DictToDec: TToDict;
    DictCount: TCountDict;
    procedure FillDicts(SM4: TSM4);
  public
    procedure SimpleDemo;
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.SimpleDemo;  //最简单使用示范代码
var
  S1, S2: String;
begin
  with TSM4.Create(cmCBC, pmPKCS5) do
  begin
    DataBuffer.FromString('先学着让自己值钱');
    KeyBuffer.FromBase64String('MTIzNDU2Nzg5MDEyMzQ1Ng=='); //1234567890123456
//或KeyBuffer.FromString('1234567890123456');
    IVBuffer.FromHexString('6162636465666768696A6B6C6D6E6F70'); //abcdefghijklmnop
    Encrypt;
    S1 := DataBuffer.ToHexString; //6C19FEC30147DBDE9539DC1DF0F3ACF09B6E6210F0F220D3D923F200DC5A44C4
    DataBuffer.FromHexString(S1);
    Decrypt;
    S2 := DataBuffer.ToString; //'先学着让自己值钱'
    Free;
  end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutDown := True;

  DIctCm := TDictionary<String, TCipherMode>.Create;
  DIctPm := TDictionary<String, TPaddingMode>.Create;

  DictFromStr := TFromDict.Create;
  DictFromKey := TFromDict.Create;
  DictFromIV  := TFromDict.Create;
  DictFromEnc := TFromDict.Create;

  DictToEnc := TToDict.Create;
  DictToDec := TToDict.Create;

  DictCount := TCountDict.Create;

  with DIctCm do
  begin
    Add('ECB' , cmECB);
    Add('CBC' , cmCBC);
    Add('CFB' , cmCFB);
    Add('OFB' , cmOFB);
    Add('PCBC', cmPCBC);
    Add('CTR' , cmCTR);
  end;

  with DIctPm do
  begin
    Add('ZERO'      , pmZERO);
    Add('PKCS5'     , pmPKCS5);
    Add('PKCS7'     , pmPKCS7);
    Add('ISO10126'  , pmISO10126);
    Add('ANSIX923'  , pmANSIX923);
    Add('OneAndZero', pmOneAndZero);
  end;

  with DictCount do
  begin
    Add(EditStr, LabelStrCnt);
    Add(EditKey, LabelKeyCnt);
    Add(EditIV , LabelIVCnt );
    Add(EditEnc, LabelEncCnt);
    Add(EditDec, LabelDecCnt);
  end;

  EditChange(nil);
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  DIctCm.Free;
  DIctPm.Free;

  DictFromStr.Free;
  DictFromKey.Free;
  DictFromIV.Free;
  DictFromEnc.Free;

  DictToEnc.Free;
  DictToDec.Free;

  DictCount.Free;
end;

procedure TMainForm.FillDicts(SM4: TSM4);
var
  DataBuffer, KeyBuffer, IVBuffer: TBuffer;
begin
  DataBuffer := SM4.DataBuffer;
  KeyBuffer := SM4.KeyBuffer;
  IVBuffer  := SM4.IVBuffer;

  with DictFromStr do
  begin
    Clear;
    Add('String', DataBuffer.FromString);
    Add('Hex'   , DataBuffer.FromHexString);
    Add('Base64', DataBuffer.FromBase64String);
  end;

  with DictFromKey do
  begin
    Clear;
    Add('String', KeyBuffer.FromString);
    Add('Hex'   , KeyBuffer.FromHexString);
    Add('Base64', KeyBuffer.FromBase64String);
  end;

  with DictFromIV do
  begin
    Clear;
    Add('String', IVBuffer.FromString);
    Add('Hex'   , IVBuffer.FromHexString);
    Add('Base64', IVBuffer.FromBase64String);
  end;

  with DictFromEnc do
  begin
    Clear;
    Add('Hex'   , DataBuffer.FromHexString);
    Add('Base64', DataBuffer.FromBase64String);
  end;

  with DictToEnc do
  begin
    Clear;
    Add('Hex'   , DataBuffer.ToHexString);
    Add('Base64', DataBuffer.ToBase64String);
  end;

  with DictToDec do
  begin
    Clear;
    Add('String', DataBuffer.ToString);
    Add('Hex'   , DataBuffer.ToHexString);
    Add('Base64', DataBuffer.ToBase64String);
  end;

end;

procedure TMainForm.ButtonConvertClick(Sender: TObject);
begin
  with TBuffer.Create do
  begin
    FromString(EditSrc.Text);
    if Sender = ButtonToHex then
      EditDest.Text := ToHexString
    else
      EditDest.Text := ToBase64String;
    Free;
  end;
end;

procedure TMainForm.ButtonFromClick(Sender: TObject);
begin
  with TBuffer.Create do
  begin
    if Sender = ButtonFromHex then
      FromHexString(EditDest.Text)
    else
      FromBase64String(EditDest.Text);
    EditSrc.Text := ToString;
    Free;
  end;
end;

procedure TMainForm.ButtonClick(Sender: TObject);
var
  SM4: TSM4;
begin
  SM4 := TSM4.Create(DIctCm.Items[ComboBoxCipherMode.Text],
                     DIctPm.Items[ComboBoxPaddingMode.Text]);
  try
    FillDicts(SM4);
    DictFromKey.Items[ComboBoxKey.Text](EditKey.Text);
    DictFromIV.Items[ComboBoxIV.Text](EditIV.Text);
    if Sender = ButtonEncrypt then
    begin
      DictFromStr.Items[ComboBoxStr.Text](EditStr.Text);
      SM4.Encrypt;
      EditEnc.Text := DictToEnc.Items[ComboBoxEnc.Text]();
    end
    else
    begin
      DictFromEnc.Items[ComboBoxEnc.Text](EditEnc.Text);
      SM4.Decrypt;
      EditDec.Text := DictToDec.Items[ComboBoxDec.Text]();
    end;
  except
  end;
  SM4.Free;
end;

procedure TMainForm.EditChange(Sender: TObject);
var
  Edit: TEdit;
begin
  if Sender <> nil then
  begin
    Edit := TEdit(Sender);
    DictCount.Items[Edit].Caption := Length(Edit.Text).ToString;
  end
  else
  begin
    for Edit in DictCount.Keys do
    begin
      DictCount.Items[Edit].Caption := Length(Edit.Text).ToString;
    end;
  end;
end;

end.

object MainForm: TMainForm
  Left = 0
  Top = 0
  Caption = 'SM4'#21152#23494#35299#23494#27979#35797
  ClientHeight = 452
  ClientWidth = 788
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poScreenCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  DesignSize = (
    788
    452)
  PixelsPerInch = 96
  TextHeight = 13
  object LabelBlockMode: TLabel
    Left = 5
    Top = 108
    Width = 48
    Height = 13
    Caption = #21152#23494#27169#24335
  end
  object LabelPaddingmode: TLabel
    Left = 132
    Top = 108
    Width = 48
    Height = 13
    Caption = #22635#20805#27169#24335
  end
  object LabelStr: TLabel
    Left = 28
    Top = 149
    Width = 24
    Height = 13
    Caption = #26126#25991
  end
  object LabelIV: TLabel
    Left = 4
    Top = 234
    Width = 48
    Height = 13
    Caption = #21021#22987#21521#37327
  end
  object LabelEnc: TLabel
    Left = 26
    Top = 314
    Width = 24
    Height = 13
    Caption = #23494#25991
  end
  object LabelDec: TLabel
    Left = 26
    Top = 402
    Width = 24
    Height = 13
    Caption = #26126#25991
  end
  object LabelKey: TLabel
    Left = 26
    Top = 193
    Width = 24
    Height = 13
    Caption = #23494#30721
  end
  object LabelStrCnt: TLabel
    Left = 758
    Top = 150
    Width = 24
    Height = 13
    Anchors = [akTop, akRight]
    Caption = #23383#25968
  end
  object LabelKeyCnt: TLabel
    Left = 758
    Top = 192
    Width = 24
    Height = 13
    Anchors = [akTop, akRight]
    Caption = #23383#25968
  end
  object LabelIVCnt: TLabel
    Left = 758
    Top = 234
    Width = 24
    Height = 13
    Anchors = [akTop, akRight]
    Caption = #23383#25968
  end
  object LabelEncCnt: TLabel
    Left = 758
    Top = 314
    Width = 24
    Height = 13
    Anchors = [akTop, akRight]
    Caption = #23383#25968
  end
  object LabelDecCnt: TLabel
    Left = 758
    Top = 400
    Width = 24
    Height = 13
    Anchors = [akTop, akRight]
    Caption = #23383#25968
  end
  object Label1: TLabel
    Left = 5
    Top = 35
    Width = 48
    Height = 13
    Caption = #23545#27604#32467#26524
  end
  object Label2: TLabel
    Left = 512
    Top = 1
    Width = 28
    Height = 13
    Caption = 'String'
  end
  object Label3: TLabel
    Left = 494
    Top = 64
    Width = 89
    Height = 13
    Caption = 'Hex/Base64 [utf8]'
  end
  object ComboBoxCipherMode: TComboBox
    Left = 59
    Top = 105
    Width = 54
    Height = 21
    TabOrder = 0
    Text = 'ECB'
    Items.Strings = (
      'ECB'
      'CBC'
      'PCBC'
      'CFB'
      'OFB'
      'CTR')
  end
  object ComboBoxPaddingmode: TComboBox
    Left = 185
    Top = 105
    Width = 68
    Height = 21
    TabOrder = 1
    Text = 'PKCS7'
    Items.Strings = (
      'ZERO'
      'PKCS5'
      'PKCS7'
      'ANSIX923'
      'OneAndZero'
      'ISO10126'
      '')
  end
  object EditKey: TEdit
    Left = 119
    Top = 188
    Width = 633
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 2
    Text = '1234567890123456'
    OnChange = EditChange
  end
  object EditIV: TEdit
    Left = 119
    Top = 230
    Width = 633
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 3
    Text = 'abcdefghijklmnop'
    OnChange = EditChange
  end
  object EditDec: TEdit
    Left = 119
    Top = 396
    Width = 633
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 4
    OnChange = EditChange
  end
  object EditEnc: TEdit
    Left = 119
    Top = 310
    Width = 633
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 5
    OnChange = EditChange
  end
  object EditStr: TEdit
    Left = 119
    Top = 146
    Width = 633
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 6
    Text = #20808#23398#30528#35753#33258#24049#20540#38065
    OnChange = EditChange
  end
  object ButtonEncrypt: TButton
    Left = 329
    Top = 268
    Width = 137
    Height = 24
    Caption = #21152#23494
    TabOrder = 7
    OnClick = ButtonClick
  end
  object ButtonDecrypt: TButton
    Left = 329
    Top = 351
    Width = 137
    Height = 24
    Caption = #35299#23494
    TabOrder = 8
    OnClick = ButtonClick
  end
  object ComboBoxStr: TComboBox
    Left = 57
    Top = 146
    Width = 58
    Height = 21
    TabOrder = 9
    Text = 'String'
    Items.Strings = (
      'String'
      'Hex'
      'Base64')
  end
  object ComboBoxKey: TComboBox
    Left = 57
    Top = 188
    Width = 58
    Height = 21
    TabOrder = 10
    Text = 'String'
    Items.Strings = (
      'String'
      'Hex'
      'Base64')
  end
  object ComboBoxIV: TComboBox
    Left = 57
    Top = 230
    Width = 58
    Height = 21
    TabOrder = 11
    Text = 'String'
    Items.Strings = (
      'String'
      'Hex'
      'Base64')
  end
  object ComboBoxEnc: TComboBox
    Left = 57
    Top = 310
    Width = 58
    Height = 21
    TabOrder = 12
    Text = 'Hex'
    Items.Strings = (
      'Hex'
      'Base64')
  end
  object ComboBoxDec: TComboBox
    Left = 57
    Top = 396
    Width = 58
    Height = 21
    TabOrder = 13
    Text = 'String'
    Items.Strings = (
      'String'
      'Hex'
      'Base64')
  end
  object EditSrc: TEdit
    Left = 361
    Top = 16
    Width = 345
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 14
    Text = #20808#23398#30528#35753#33258#24049#20540#38065
  end
  object ButtonToHex: TButton
    Left = 293
    Top = 41
    Width = 62
    Height = 22
    Caption = 'ToHex'
    TabOrder = 15
    OnClick = ButtonConvertClick
  end
  object ButtonToBase64: TButton
    Left = 713
    Top = 41
    Width = 65
    Height = 22
    Anchors = [akTop, akRight]
    Caption = 'ToBase64'
    TabOrder = 16
    OnClick = ButtonConvertClick
  end
  object EditDest: TEdit
    Left = 361
    Top = 41
    Width = 345
    Height = 21
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 17
  end
  object RzEdit1: TEdit
    Left = 57
    Top = 32
    Width = 196
    Height = 21
    TabOrder = 18
    Text = 'https://javalang.cn/crypto/sm4.html'
  end
  object ButtonFromHex: TButton
    Left = 294
    Top = 16
    Width = 61
    Height = 22
    Caption = 'FromHex'
    TabOrder = 19
    OnClick = ButtonFromClick
  end
  object ButtonFramBase64: TButton
    Left = 713
    Top = 15
    Width = 65
    Height = 22
    Anchors = [akTop, akRight]
    Caption = 'FromBase64'
    TabOrder = 20
    OnClick = ButtonFromClick
  end
end

unit uSM4;

{procedure SimpleDemo;  //最简单使用示范代码
var
  S1, S2: String;
begin
  with TSM4.Create(cmCBC, pmPKCS5) do
  begin
    DataBuffer.FromString('先学着让自己值钱');
    KeyBuffer.FromBase64String('MTIzNDU2Nzg5MDEyMzQ1Ng=='); //1234567890123456
    IVBuffer.FromHexString('6162636465666768696A6B6C6D6E6F70'); //abcdefghijklmnop
    Encrypt;
    S1 := DataBuffer.ToHexString; //6C19FEC30147DBDE9539DC1DF0F3ACF09B6E6210F0F220D3D923F200DC5A44C4

    DataBuffer.FromHexString(S1);
    Decrypt;
    S2 := DataBuffer.ToString; //'先学着让自己值钱'
    Free;
  end;
end;}

interface

uses
{$IF CompilerVersion <= 22}
  Forms, Classes, Windows, SysUtils, NetEncoding,
{$ELSE}
  Vcl.Forms, System.Classes, Winapi.Windows, System.SysUtils, System.NetEncoding,
{$ENDIF}
  uBuffer;

type
  TCipherMode  = (cmECB, cmCBC, cmPCBC, cmCFB, cmOFB, cmCTR);
  TPaddingMode = (pmZERO, pmPKCS5, pmPKCS7, pmISO10126, pmANSIX923, pmOneAndZero);

  TSM4 = class(TObject)
  private type
    TWord = UInt32; //4 Bytes
    TBlock = array[0..4-1] of TWord;  //4 TWords
    TRoundKey = array[0..32-1] of TWord; //32 TWords
    TCryptType = (ctEncrypt, ctDecrypt);
  private const
    BlockSize = 4 * SizeOf(TWord); //16 Bytes
  private
    RoundKey: TRoundKey;
    KeyBlock, IVBlock, InBlock: TBlock;
    CipherMode : TCipherMode;
    PaddingMode: TPaddingMode;
    CryptType: TCryptType;
    procedure AppendPadding;
    procedure RemovePadding;
    procedure CheckKeyBufferAndIVBuffer;
    procedure Crypt;
    procedure ExpandKey;
    procedure CipherBlock(var aDataBlock);
    procedure CryptBlock(const aCryptType: TCryptType; var A: TBlock);
    function  SBoxMap(A: TWord): TWord;
    function  ROTL(A: TWord; N: Byte): TWord;
    procedure ReverseEndian(var A: TBlock);
    procedure XorBlock(var A: TBlock; const B: TBlock); overload;
    procedure XorBlock(var A: TBlock; const B, C: TBlock); overload;
    procedure IncBlock(Var A: TBlock);
  public
    DataBuffer, KeyBuffer, IVBuffer: TBuffer;
    procedure Encrypt;
    procedure Decrypt;
    constructor Create(aCipherMode: TCipherMode  = cmECB;
                      aPaddingMode: TPaddingMode = pmPKCS7);
    destructor Destroy; override;
  end;

implementation

const
// S盒
  Sbox: array[0..255] of Byte = (
    $d6,$90,$e9,$fe,$cc,$e1,$3d,$b7,$16,$b6,$14,$c2,$28,$fb,$2c,$05,
    $2b,$67,$9a,$76,$2a,$be,$04,$c3,$aa,$44,$13,$26,$49,$86,$06,$99,
    $9c,$42,$50,$f4,$91,$ef,$98,$7a,$33,$54,$0b,$43,$ed,$cf,$ac,$62,
    $e4,$b3,$1c,$a9,$c9,$08,$e8,$95,$80,$df,$94,$fa,$75,$8f,$3f,$a6,
    $47,$07,$a7,$fc,$f3,$73,$17,$ba,$83,$59,$3c,$19,$e6,$85,$4f,$a8,
    $68,$6b,$81,$b2,$71,$64,$da,$8b,$f8,$eb,$0f,$4b,$70,$56,$9d,$35,
    $1e,$24,$0e,$5e,$63,$58,$d1,$a2,$25,$22,$7c,$3b,$01,$21,$78,$87,
    $d4,$00,$46,$57,$9f,$d3,$27,$52,$4c,$36,$02,$e7,$a0,$c4,$c8,$9e,
    $ea,$bf,$8a,$d2,$40,$c7,$38,$b5,$a3,$f7,$f2,$ce,$f9,$61,$15,$a1,
    $e0,$ae,$5d,$a4,$9b,$34,$1a,$55,$ad,$93,$32,$30,$f5,$8c,$b1,$e3,
    $1d,$f6,$e2,$2e,$82,$66,$ca,$60,$c0,$29,$23,$ab,$0d,$53,$4e,$6f,
    $d5,$db,$37,$45,$de,$fd,$8e,$2f,$03,$ff,$6a,$72,$6d,$6c,$5b,$51,
    $8d,$1b,$af,$92,$bb,$dd,$bc,$7f,$11,$d9,$5c,$41,$1f,$10,$5a,$d8,
    $0a,$c1,$31,$88,$a5,$cd,$7b,$bd,$2d,$74,$d0,$12,$b8,$e5,$b4,$b0,
    $89,$69,$97,$4a,$0c,$96,$77,$7e,$65,$b9,$f1,$09,$c5,$6e,$c6,$84,
    $18,$f0,$7d,$ec,$3a,$dc,$4d,$20,$79,$ee,$5f,$3e,$d7,$cb,$39,$48
  );

// 密钥扩展算法的常数FK
  FK: array[0..3] of UInt32 = ($a3b1bac6, $56aa3350, $677d9197, $b27022dc);

// 密钥扩展算法的固定参数CK
  CK: array[0..31] of UInt32 = (
    $00070e15, $1c232a31, $383f464d, $545b6269,
    $70777e85, $8c939aa1, $a8afb6bd, $c4cbd2d9,
    $e0e7eef5, $fc030a11, $181f262d, $343b4249,
    $50575e65, $6c737a81, $888f969d, $a4abb2b9,
    $c0c7ced5, $dce3eaf1, $f8ff060d, $141b2229,
    $30373e45, $4c535a61, $686f767d, $848b9299,
    $a0a7aeb5, $bcc3cad1, $d8dfe6ed, $f4fb0209,
    $10171e25, $2c333a41, $484f565d, $646b7279
);

constructor TSM4.Create(aCipherMode: TCipherMode; aPaddingMode: TPaddingMode);
begin
  inherited Create;
  CipherMode  := aCipherMode;
  PaddingMode := aPaddingMode;
  DataBuffer := TBuffer.Create;
  KeyBuffer  := TBuffer.Create;
  IVBuffer   := TBuffer.Create;
end;

destructor TSM4.Destroy;
begin
  DataBuffer.Free;
  KeyBuffer.Free;
  IVBuffer.Free;
  inherited;
end;

procedure TSM4.Encrypt;
begin
  AppendPadding;
  CryptType := ctEncrypt;
  Crypt;
end;

procedure TSM4.Decrypt;
begin
  CryptType := ctDecrypt;
  Crypt;
  RemovePadding;
end;

procedure TSM4.AppendPadding; //添加填充
var
  I, M, N, Len, NewLen: Integer;
begin
  Len := DataBuffer.Length;
  M := (Len mod BlockSize);
  if  (PaddingMode = pmZERO) and (M = 0) then
    N := 0
  else
    N := BlockSize - M;
  NewLen := Len + N;
  DataBuffer.Length := NewLen;

  case PaddingMode of
    pmPKCS5, pmPKCS7:
    begin
      for I := Len to NewLen-1 do DataBuffer[I] := N;
    end;
    pmANSIX923:
    begin
      for I := Len to NewLen-1 do
      begin
        if I < NewLen-1 then
          DataBuffer[I] := 0
        else
          DataBuffer[I] := N;
      end;
    end;
    pmISO10126:
    begin
      Randomize;
      for I := Len to NewLen-1 do
      begin
        if I < NewLen-1 then
          DataBuffer[I] := Random(255)
        else
          DataBuffer[I] := N;
      end;
    end;
    pmZERO:
    begin
      for I := Len to NewLen-1 do DataBuffer[I] := 0;
    end;
    pmOneAndZero:
    begin
      for I := Len to NewLen-1 do
      begin
        if I = Len then
          DataBuffer[I] := $80
        else
          DataBuffer[I] := 0;
      end;
    end;
  end;
end;

procedure TSM4.RemovePadding; //移除填充
var
  I, M, Len: Integer;
begin
  Len := DataBuffer.Length;
  case PaddingMode of
    pmPKCS5, pmPKCS7, pmANSIX923, pmISO10126:
    begin
      M := DataBuffer[Len-1];
      DataBuffer.Length := Len-M;
    end;
    pmZERO:
    begin
      for I := Len-1 downto 0 do
      begin
        if DataBuffer[I] = 0 then
          Dec(Len)
        else
          Break;
      end;
      DataBuffer.Length := Len;
    end;
    pmOneAndZero:
    begin
      for I := Len-1 downto 0 do
      begin
        if DataBuffer[I] <> $80 then
          Dec(Len)
        else
          Break;
      end;
      DataBuffer.Length := Len-1;
    end;
  end;
end;

procedure TSM4.CheckKeyBufferAndIVBuffer; //对Key和IV不足16Bytes的情况以0填足
var
  I, Len: Integer;
begin
  Len := KeyBuffer.Length;
  KeyBuffer.Length := BlockSize;
  for I := Len to BlockSize - 1 do
  begin
    KeyBuffer[I] := 0;
  end;

  if CipherMode <> cmECB then //ECB模式不需要初始向量IV
  begin
    Len := IVBuffer.Length;
    IVBuffer.Length := BlockSize;
    for I := Len to BlockSize - 1 do
    begin
      IVBuffer[I] := 0;
    end;
  end;
end;

procedure TSM4.Crypt;
var
  I: Integer;
  Memory: PByte;
begin
  CheckKeyBufferAndIVBuffer;

  KeyBuffer.ToBytes(KeyBlock, BlockSize);
  ExpandKey;

  if CipherMode <> cmECB then
  begin
    IVBuffer.ToBytes(IVBlock, BlockSize);
  end;

  Memory := DataBuffer.Memory;
  for I := 0 to (DataBuffer.Length div BlockSize)-1 do
  begin
    CipherBlock(Memory^);
    //为提高效率, 加密过程直接使用了DataBuffer的内存, 以避免内存来回拷贝
    Inc(Memory, BlockSize);
  end;
end;

procedure TSM4.CipherBlock(var aDataBlock);
var
  DataBlock: TBlock absolute aDataBlock;   //16 bytes -> 1 Block
begin
  case CipherMode of
    cmECB: //Electronic Codebook (ECB)
      begin
        CryptBlock(CryptType, DataBlock);
      end;
    cmCBC: //Cipher Block Chaining (CBC)
      begin
        if CryptType = ctEncrypt then
        begin
          XorBlock(DataBlock, IVBlock);
          CryptBlock(CryptType, DataBlock);
          IVBlock := DataBlock;
        end
        else
        begin
          InBlock := DataBlock;
          CryptBlock(CryptType, DataBlock);
          XorBlock(DataBlock, IVBlock);
          IVBlock := InBlock;
        end;
      end;
    cmPCBC: //Propagating Cipher Block Chaining (PCBC)
      begin
        InBlock := DataBlock;
        if CryptType = ctEncrypt then
        begin
          XorBlock(DataBlock, IVBlock);
          CryptBlock(CryptType, DataBlock);
        end
        else
        begin
          CryptBlock(CryptType, DataBlock);
          XorBlock(DataBlock, IVBlock);
        end;
        XorBlock(IVBlock, DataBlock, InBlock);
      end;
    cmCFB: //Cipher Feedback (CFB)
      begin
        InBlock := DataBlock;
        CryptBlock(ctEncrypt, IVBlock); //不管是加密还是解密,这里都是用Encrypt对IV进行操作
        XorBlock(DataBlock, IVBlock);
        if CryptType = ctEncrypt then
          IVBlock := DataBlock
        else
          IVBlock  := InBlock;
      end;
    cmOFB: //Output Feedback (OFB)
      begin
        CryptBlock(ctEncrypt, IVBlock); //不管是加密还是解密,这里都是用Encrypt对IV进行操作
        XorBlock(DataBlock, IVBlock);
      end;
    cmCTR: //Counter (CTR)
      begin
        InBlock := IVBlock;
        CryptBlock(ctEncrypt, InBlock); //不管是加密还是解密,这里都是用Encrypt对IV进行操作
        XorBlock(DataBlock, InBlock);
        IncBlock(IVBlock);
      end;
  end;
end;

procedure TSM4.ExpandKey;  //密钥扩展, 使用了FK常量和CK常量
  function Transform(A: TWord): TWord; //合成置换
  begin
    A := SBoxMap(A); //非线性变换
    Result := A xor ROTL(A, 13) xor ROTL(A, 23); //线性变换
  end;
var
  K: TBlock;
  I: Integer;
  M0, M1, M2, M3: TWord;
begin
  ReverseEndian(KeyBlock); //32整数转换为大端(Big Endian)格式

  for I := 0 to 3 do
  begin
    K[I] := KeyBlock[I] xor FK[I]; //Key先和常数FK做异或运算
  end;

  for I := 0 to 31 do //32次迭代运算
  begin
    M0 := (I  ) mod 4;
    M1 := (I+1) mod 4;
    M2 := (I+2) mod 4;
    M3 := (I+3) mod 4;
    K[M0] := K[M0] xor Transform(K[M1] xor K[M2] xor K[M3] xor CK[I]); //迭代运算
    RoundKey[I] := K[M0];
  end;
end;

procedure TSM4.CryptBlock(const aCryptType: TCryptType; var A: TBlock); //对Block加密
  function Transform(A: TWord): TWord; //合成置换
  begin
    A := SBoxMap(A); //非线性变换
    Result := A xor ROTL(A, 2) xor ROTL(A, 10) xor ROTL(A, 18) xor ROTL(A, 24); //线性变换
  end;
var
  T: TBlock;
  I,  R: Integer;
  M0, M1, M2, M3: TWord;
begin
  ReverseEndian(A); //32整数转换为大端(Big Endian)格式

  for I := 0 to 31 do  //32次迭代运算
  begin
    if aCryptType = ctEncrypt then
      R := I
    else
      R := 31 - I;  //解密时使用反序的RoundKey

    M0 := (I  ) mod 4;
    M1 := (I+1) mod 4;
    M2 := (I+2) mod 4;
    M3 := (I+3) mod 4;

    A[M0] := A[M0] xor TransForm(A[M1] xor A[M2] xor A[M3] xor RoundKey[R]); //迭代运算
  end;

  ReverseEndian(A); //32整数转换为小端(Little Endian)格式

  T := A;
  for I := 0 to 3 do //Block内部的4个32位整数的位置做反序变换
  begin
    A[I] := T[3 - I];
  end;
end;

function TSM4.SBoxMap(A: TWord): TWord; //S盒非线性变换(Byte to Byte的固定映射}
var
  I: Integer;
  B: array[0..3] of Byte absolute A;
  R: array[0..3] of Byte absolute Result;
begin
  for I := 0 to 3 do
  begin
    R[I] := SBox[B[I]];
  end;
end;

procedure TSM4.ReverseEndian(var A: TBlock); //对Block里面的4个32位整数都做大小端(Endian)变换
var
  I: Integer;
begin
  for I := 0 to 3 do
  begin
    A[I] := ( A[I] shr 24) or
            ((A[I] and $00FF0000) shr 8 ) or
            ((A[I] and $0000FF00) shl 8 ) or
            ( A[I] shl 24);
  end;
end;

function TSM4.ROTL(A: TWord; N: Byte): TWord; //32位循环左移N位
begin
  Result := (A shl N) or (A shr (32-N));
end;

procedure TSM4.XorBlock(var A: TBlock; const B: TBlock); //两个Block异或
var
  I: Integer;
begin
  for I := 0 to 3 do
  begin
    A[I] := A[I] xor B[I];
  end;
end;

procedure TSM4.XorBlock(var A: TBlock; const B, C: TBlock); //两个Block异或
var
  I: Integer;
begin
  for I := 0 to 3 do
  begin
    A[I] := B[I] xor C[I];
  end;
end;

procedure TSM4.IncBlock(var A: TBlock); //Block值加1
var
  I: Integer;
  B: array[0..15] of Byte absolute A;
begin
  for I := 15 downto 0 do
  begin
    Inc(B[I]);
    if B[I] <> 0 then Break;
  end;
end;

//---------------------------------------------------------------------------//

end.
unit uBuffer;

interface

uses
{$IF CompilerVersion <= 22}
  Forms, Classes, Windows, SysUtils, NetEncoding;
{$ELSE}
  Vcl.Forms, System.Classes, Winapi.Windows, System.SysUtils, System.NetEncoding;
{$ENDIF}

type
  TBuffer = class(TObject)
  private
    Data: TBytes;
    function  GetMemory: PByte; inline;
    function  GetDataLength: Integer; inline;
    procedure SetDataLength(Len: Integer); inline;
    function  GetItem(Index: Integer): Byte; inline;
    procedure SetItem(Index: Integer; Value: Byte); inline;
  public
    procedure FromString(const S: String); overload;  //默认为utf8
    procedure FromString(const S: String; Encoding: TEncoding); overload;
    procedure FromDelimitedDecimalString(const S: String; Delimitor: Char = ',');
    procedure FromHexString(const S: String);
    procedure FromDelimitedHexString(S: String; Prefix: String = '$'; Delimitor: String = ',');
    procedure FromBase64String(const S: String);
    procedure FromBytes(const Source; Len: Integer);
    procedure FromStream(const Stream: TStream; ByteLen: Integer = -1);
    procedure FromFile(const FileName: String);

    function  ToString: String; reintroduce; overload;  //默认为utf8
    function  ToString(Encoding: TEncoding): String; reintroduce; overload;
    function  ToDelimitedDecimalString(Delimitor: Char = ','): String;
    function  ToHexString: String;
    function  ToDelimitedHexString(Prefix: String = '$'; Delimitor: String = ', '): String;
    function  ToBase64String: String;
    procedure ToBytes(var Dest; Len: Integer);
    procedure ToStream(const Stream: TStream);
    procedure ToFile(const FileName: String; Warning: Boolean = True);

    property  Memory: PByte read GetMemory;
    property  Length: Integer read GetDataLength write SetDataLength;
    property  Items[Index: Integer]: Byte read GetItem write SetItem; default;
  end;

implementation

function TBuffer.GetMemory: PByte;
begin
  Result := @Data[0];
end;

function TBuffer.GetDataLength: Integer;
begin
  Result := System.Length(Data);
end;

procedure TBuffer.SetDataLength(Len: Integer);
begin
  System.SetLength(Data, Len);
end;

function  TBuffer.GetItem(Index: Integer): Byte;
begin
  Result := Data[Index];
end;

procedure TBuffer.SetItem(Index: Integer; Value: Byte);
begin
  Data[Index] := Value;
end;

procedure TBuffer.FromString(const S: String);
begin
  Data := TEncoding.UTF8.GetBytes(S);
end;

procedure TBuffer.FromString(const S: String; Encoding: TEncoding);
begin
  Data := Encoding.GetBytes(S);
end;

procedure TBuffer.FromDelimitedDecimalString(const S: String; Delimitor: Char);
var
  I, Len: Integer;
  List: TStringList;
begin
  List := TStringList.Create;
  List.Delimiter := Delimitor;
  List.DelimitedText := S;
  Len := List.Count;
  SetLength(Data, Len);
  for I := 0 to Len-1 do
  begin
    Data[I] := StrToUInt(List[I]);
  end;
  List.Free;
end;

procedure TBuffer.FromHexString(const S: String);
var
  Len: Integer;
begin
  Len := System.Length(S) div 2;
  SetLength(Data, Len);
  HexToBin(PChar(S), Data[0], Len)
end;

procedure TBuffer.FromDelimitedHexString(S: String; Prefix: String; Delimitor: String);
var
  Len: Integer;
begin
  S := S.Replace(Prefix   , '');
  S := S.Replace(Delimitor, '');
  S := S.Replace(' '      , '');
  Len := System.Length(S) div 2;
  SetLength(Data, Len);
  HexToBin(PChar(S), Data[0], Len)
end;

procedure TBuffer.FromBase64String(const S: String);
var
  Base64Encoding: TBase64Encoding;
begin
//Base64Encoding := TBase64Encoding.Create; //含换行符
  Base64Encoding := TBase64Encoding.Create(0); //不含换行符
  Data := Base64Encoding.DecodeStringToBytes(S);
  Base64Encoding.Free;
end;

procedure TBuffer.FromBytes(const Source; Len: Integer);
begin
  SetLength(Data, Len);
  Move(Source, Data[0], Len);
end;

procedure TBuffer.FromStream(const Stream: TStream; ByteLen: Integer);
begin
  if (ByteLen = -1) then ByteLen := Stream.Size;
  SetLength(Data, ByteLen);
  Stream.Read(Data, ByteLen);
end;

procedure TBuffer.FromFile(const FileName: String);
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create(FileName, fmOpenRead);
  SetLength(Data, Stream.Size);
  Stream.Read(Data, Stream.Size);
  Stream.Free;
end;

function TBuffer.ToString: String;
begin
  Result := TEncoding.UTF8.GetString(Data);
end;

function TBuffer.ToString(Encoding: TEncoding): String;
begin
  Result := Encoding.GetString(Data);
end;

function TBuffer.ToDelimitedDecimalString(Delimitor: Char): String;
var
  I: Integer;
begin
  Result := '';
  for I := 0 to System.Length(Data)-1 do
  begin
    if I > 0 then
    begin
      Result := Result + Delimitor + ' ';
    end;
    Result := Result +  Data[I].ToString
  end;
end;

function TBuffer.ToHexString: String;
var
  Len: Integer;
begin
  Len := System.Length(Data);
  SetLength(Result, 2*Len);
  BinToHex(Data[0], PChar(Result), Len);
end;

function TBuffer.ToDelimitedHexString(Prefix: String; Delimitor: String): String;
var
  I, Len: Integer;
begin
  Result := '';
  Len := System.Length(Data);
  for I := 0 to Len-1 do
  begin
    Result := Result + Prefix + IntToHex(Data[I], 2);
    if I < Len-1 then
      Result := Result + Delimitor;
  end;
end;

function TBuffer.ToBase64String: String;
var
  Base64Encoding: TBase64Encoding;
begin
//Base64Encoding := TBase64Encoding.Create; //含换行符
  Base64Encoding := TBase64Encoding.Create(0); //不含换行符
  Result := Base64Encoding.EncodeBytesToString(Data);
  Base64Encoding.Free;
end;

procedure TBuffer.ToBytes(var Dest; Len: Integer);
begin
  Move(Data[0], Dest, Len);
end;

procedure TBuffer.ToStream(const Stream: TStream);
begin
  Stream.Write(Data, System.Length(Data));
end;

procedure TBuffer.ToFile(const FileName: String; Warning: Boolean);
var
  Stream: TFileStream;
begin
  if Warning and FileExists(FileName) and
     (Application.MessageBox(PChar('File ' + FileName + ' Exists, Overwrite It?'),
                  'Warning: File Exists', MB_YESNO) = IDNO)  then Exit;

  Stream := TFileStream.Create(FileName, fmCreate);
  Stream.Write(Data, System.Length(Data));
  Stream.Free;
end;

end.

国密算法实现文件加密解密,用到了sm2,sm3,sm4算法,delph7可以编译运行 国密算法实现文件加密,用到了sm2,sm3,sm4算法,签名,验签,生成密钥对,加密解密,包括所有示例源码,delphi7可以编译运行。 立即下载

相关推荐

delphi XE2实现与网页互通的SM2国密加解密算法

本demo实现了可与网页版互通的SM2加解密方法,封装了cnpack组件包相关功能,但可以免安装组件包。可生成密钥对、加解密字符串,同时支持Hex/Base64两种输出模式

Delphi SM2/SM4国密算法

Delphi SM2/SM4国密算法在国家医保平台中的应用场景

njbudong的专栏 4217

delphi7 国密算法实现文件加密解密 用到了sm2,sm3,sm4算法(源码+测试可用)

delphi7 国密算法实现文件加密解密 用到了sm2,sm3,sm4算法(源码+测试可用)

Delphi7 SM4加解密源码(适用于处方流转接口)

Delphi7纯源码实现SM4加解密,已经经过验证。实际参与加密的只有前16位密钥。技术交流Q1614840052。data 字段加密。appId(id)作为 Key 加密 appSecret(应用秘钥)生成新的秘钥串;再使用新秘钥串对报文的。根据 SM4 加密算法,sm4 算法使用 ECB 模式,填充算法为 PKCS7。

xurunxian的博客 1695

Delphi 12.3控件之东软数据平台-SM4-加解密-demo.7z

Delphi 12.3控件之东软数据平台-SM4-加解密-demo.7z

单片机按键识别篇---单击---双击----长按

  最近做一任务需要使用一个按键实现三种功能,分别是按键单击功能,按键双击功能和按键长按功能,可能之前没有接触过这类按键复用情况,顶多也只是简单识别单击和长按,没有想过双击以上按键功能,也是绞尽脑汁,想了半天,又上网看了些例程,算是对于按键的识别有点小小的了解,感觉这个功能挺实用,在此做个随笔。 一、思路   1.识别长按操作思路:我们使用系统定时器定时,然后让系统每过一段时间去扫描按键I/O...

weixin_30311605的博客 3660

国密算法SM4加密、SM4解密示例(二)

虽然都是国密算法SM4,但是随着厂商不一样,每个厂商的使用方法不一样,导致厂商提供的测试SM4密钥不一样,SM4结果也不一样;区分CBC、ECB等各种模式。今天就给大家介绍一些示例,都是各种对接过程中的存货,会拆分成几个文章进行讲解。SM4密钥:3046022100c3866c14853c82d71c8908cac7ddddf98aa255c824faa2d725fee62026ebd0a4022100b299665056ccf6f73ca179c0c6caa6e6d58811fdd3c63d834881a

2766

Python XML 转 JSON,XML 转字典

今天我们将学习如何在 Python 中将 XML 转换为 JSON 和 XML 转换为字典。我们可以使用 Python 的xmltodict模块来读取 XML 文件并将其转换为字典或 JSON 数据。我们还可以在大型 XML 文件上进行流式处理,并将其转换为字典。在进入编码部分之前,让我们首先了解为什么需要进行 XML 转换。

rubys_的专栏 2503

关于SMS编码Delphi源码摘抄

1.英文编码function Encode7bit(Src:String):String;var Dst:String;    i:Integer;    CurS,NextS:Byte;    TStr:String;begin  for i:=1 to Length(Src) do begin    //当前是字符按8位分组的第8位,无需编码(8个字符已缩短为7个)    if (i mod

SAP BLOG--Jack Wu 2721

基于 YOLOv26 的金属表面缺陷检测系统:智能视觉质检方案

摘要: 基于YOLOv26的金属表面缺陷检测系统采用深度学习技术,实现对划痕、裂纹、腐蚀等8类常见缺陷的自动化检测。系统通过数据增强预处理和YOLOv26模型的高精度识别能力,具备多类别分类、实时推理和强鲁棒性特点,适用于不同金属材质与光照条件。架构包含数据采集、预处理、YOLOv26检测和后处理模块,代码实现采用PyTorch框架,支持训练数据增强与标准化处理,为工业质检提供高效智能解决方案。

一键难忘的博客 589

Doris实战——结合Flink构建极速易用的实时数仓

Doris实战——结合Flink构建极速易用的实时数仓

爱吃辣条的博客 8233

Delphi Delphi7 SM2签名 SM2验签 SM3摘要 SM4加密 SM4解密 SM2加密 SM2解密 RSA加密 RSA解密 RSA签名 JSON排序算法,适配各种医保接口等

Delphi Delphi7 SM2签名 SM2验签 SM3摘要 SM4加密 SM4解密 SM2加密 SM2解密 RSA加密 RSA解密 RSA签名 JSON排序算法,适配各种医保接口等

xurunxian的博客 2506

C# WinForm上位机:从串口调试工具到智能温控系统(Modbus RTU协议实战+完整源码)

做工业上位机开发时,我们常从串口调试工具入手:验证设备通信、查看数据帧,但面对实际场景(比如温控、电机控制),单纯的“收发数据”远远不够——需要解析工业标准协议(如Modbus RTU)、实时监控关键指标、实现自动化控制逻辑,还要有稳定的UI交互和数据记录。串口调试工具能收发数据,但看不懂Modbus RTU帧(地址、功能码、寄存器、CRC校验);想控制温控设备(如加热器、风扇),但不知道如何通过Modbus写入控制指令;手动调节目标温度时,温度波动大,需要PID算法实现精准控温,但不会集成;

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1304

Delphi加密解密算法

http://www.cnblogs.com/huangygdelphi/articles/2283465.html // 加密方法一(通过密钥加密解密) function EncryptString(Source, Key: string): string; function UnEncryptString(Source, Key: string): string; //加密方法二(通过

l799623787的专栏 1580

第 2 章:PassThrough 直通滤波

通过设置某个维度(如 x、y、z 或 rgb)的取值范围,仅保留该范围内的点,从而达到**点云裁剪(裁边)**或过滤异常值的目的。所有在该范围之外的点会被移除(可选是否保留);点云中包含背景、地面或传感器噪声,需要过滤;通过 z 轴过滤,只保留桌面上方的物体;多轴组合过滤(如同时过滤 x、y、z);可用于地面剔除、车载点云预处理等场景。不支持一次过滤多个字段,可多次调用;仅处理某一层或某一区域的点云数据。原始点云中包含地面、墙面、背景等;在区域裁剪、前景提取中广泛使用;设定一个轴(如z轴);

yumeiguo的博客 337

混合精度训练与推理:平衡性能与效率

在深度学习领域,模型的训练和推理通常需要大量的计算资源和时间。随着模型规模的不断增大,如大型语言模型、复杂的视觉模型等,对计算资源的需求也呈指数级增长。混合精度训练与推理技术应运而生,它通过在训练和推理过程中同时使用不同精度的数据类型,在保证模型性能的前提下,显著提高计算效率,减少内存占用。本文的目的是全面介绍混合精度训练与推理技术,包括其原理、实现方法、应用场景以及相关工具和资源,帮助读者深入理解并掌握该技术,从而在实际项目中更好地平衡性能与效率。

操作系统内核探秘的博客 1068

Delphi7实现医保移动支付接口的SM4加解密以及SM3摘要的计算和SM2签名和验签

Delphi7纯源码实现的SM4加解密以及SM3摘要的计算,可用在各地区医保移动支付等接口中,此类接口中所用的SM4加解密有区别于处方流转接口,需要做urlbase64转化。param={“userId”:“abc123”}&参数=参数值…最后加上&key=密钥。业务接口请求参数使用未加密前的数据按 JOSN 格式字符串用 param 作为参数。式,并且把这些参数用&字符连接起来,最后拼接上以"key"作为参数名的接入。名参与排序与签名,将排序后的参数与其对应值,组合成“参数=参数值”的格。

xurunxian的博客 1666

MongoDB分布式事务实现:两阶段提交、日志复制与冲突解决

MongoDB分布式事务机制解析 本文深入剖析了MongoDB 4.0+版本的分布式事务实现原理,重点分析了其在跨文档/跨集合/跨分片场景下的数据一致性解决方案。核心内容包括: 底层机制:采用改进的两阶段提交协议,通过oplog日志复制实现无中心协调器的事务管理,结合WiredTiger存储引擎和锁机制保障ACID特性。 创新设计:将传统2PC的中心协调功能分散到Primary节点,利用oplog作为事务状态记录,实现自动故障恢复和60秒超时回滚机制。 性能优化:针对大事务、写冲突等常见问题,提出拆分微事务

数据知道的博客 1261

delphi电子处方流转 sm2 sm4(医院)

【delphi电子处方流转 sm2 sm4(医院)】支持 就诊登记、电子处方上传预核验、处方处方医保电子签名、电子处方上传、电子处方撤销、电子处方信息查询、电子处方审核结果查询、电子处方取药结果查询、电子处方药品目录查询等功能。

芝麻卖瓜的博客 754

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Delphi中的加密算法(MD5,MD4,MD3...)

在Delphi自带的Indy控件中其实是提供了MD2,MD4,MD5对象的,我们可以直接使用它们来完成MD5的签名算法。而不需要再去找其它的DLL或是Pas了。在Uses单元中引用 IdHashMessageDigest 单元,再写如下代码即可以达到MD5的实现。示例代码procedure TForm1.Button1Click(Sender: TObject);var  MyMD5: TId

虫二的专栏~~在路上~~~ 3764

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

国密SM2加密解密、签名验签;SM3摘要,SM4加解密源码

国密SM2加密解密、签名验签;SM3摘要,SM4加解密源码: 开源地址: https://gitee.com/ren365880/sm-java.git

梦里蓝天 1万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

DELPHI 自己写的经常用到的加解密函数

以下程序可直接用,拷贝就可以了,希望可以起到抛砖引玉的作用。 function StrDecrypt(s: string; key: word): string; var   i:byte; const   fc1=2;   fc2=3; begin   //result[0]:=s[0];   setlength(result,length(s));   for i:=1

全欣 的专栏 2270

Delphi 版 SM3 & SM4 加密解密代码

Delphi 版 SM3 & SM4 加密解密代码 去发现同类优质开源项目:https://gitcode.com/ 简介 本仓库提供了适用于 Delphi 编程语言的 SM3 杂凑算法和 SM4 加密解密库。此代码库在 Delphi 7 和 Delphi 2010 版本下进行了测试,并尽可能考虑了版本兼容性,以便在其他 Delphi 版本上使用时问题不大。 功能特性 SM4 ECB 模...

gitblog_06747的博客 612

医保SM2签名SM4加密解密

医保SM2签名SM4加密解密

songyousha的博客 1261

国密SM4加解密算法DELPHI原码:安全加密的DELPHI解决方案

国密SM4加解密算法DELPHI原码:安全加密的DELPHI解决方案 去发现同类优质开源项目:https://gitcode.com/ 国密SM4加解密算法DELPHI原码,是DELPHI环境下实现国密SM4算法的一个开源项目。本文将深入探讨这个项目的核心功能、技术分析、应用场景及特点,帮助您了解其在安全加密领域的价值和实用性。 项目介绍 国密SM4加解密算法DELPHI原码,为DELPHI开发者...

gitblog_06781的博客 820

【国密算法那点事儿】解读DES和SM4、RSA和SM2及SHA和SM3

转载自:http://www.wtoutiao.com/a/844743.html 安全是智能卡的核心,而算法是安全的基础。 国密算法由国家密码局发布,包含SM1\ SM2\ SM3\ SM4\ SSF33算法;国际算法由美国的安全局发布,是现今最通用的商用算法。今天小钞就以分组密码算法(DES和SM4)、公钥密码算法(RSA和SM2)、摘要算法(SM3)为例,和大家谈谈国际算法和

若尘风 6万+
上一篇: 在Delphi程序中提取本身的DFM资源数据
下一篇: [Delphi]一个功能完备的国密SM3(杂凑值,或称为哈希值、散列值、摘要)类(TSM3)
BlueStorm
博客等级 码龄25年 74粉丝 38原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值