[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

基于cat12和SPM12进行VBM&SBM数据分析笔记1——数据预处理

基于cat12数据分析基础教程笔记 今年是小编步入研究生生活的第一年,研究方向待定,但主要以磁共振成像为主,以后会不断地总结这方面的知识,涉及MRI扫描,数据分析基础方法理论,软件操作教程,文献阅读笔记总结等等,用来记录我的研究生三年学习过程。编写尽量简洁明了,通俗易懂,本就是小白,也能体会小白的痛。不过这也要谢谢一个人手动@小白(网名),是他教我要把自己所学的写下来,讲出来才能真正的做到输入和输出,查漏补缺。而cat12软件操作是我面临的第一个数据分析的训练,写的可能也不会非常到位,还望各位专业人士指出改

Sophia2023的博客 4万+

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

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

2766

告别密码本!用Windows NPS给华为/华三交换机做Radius认证,SSH登录更安全

本文详细介绍了如何利用Windows NPS实现华为/华三交换机的Radius认证,提升SSH登录安全性。通过集中化管理、精细化控制和完整审计追踪,企业可告别传统密码本,大幅提升网络设备管理效率。文章包含NPS服务部署指南、交换机配置详解及调试技巧,助力企业构建安全高效的统一认证体系。

weixin_42549723的博客 419

关于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

Tiff、jpg图片怎么样添加地理坐标信息

Tiff、jpg图片怎么样添加地理坐标信息 一般,外业调查只有地图资料,如专题图、或者地形图,如何把这些地图资料的扫描地图带上坐标信息,从而内业实现信息化处理?以上问题,可以解决,但根据不同情况有不同的处理方法。     第一种,上面有经纬度外框,图片是矩形,但是没有地理信息。 通过图框的两个角的坐标确定范围,分别是左上(140°E,30°N);右下(150°W,30°N) 解决方

树木_xzw的博客 2万+

Vivado XDMA仿真实战:从配置到链路训练全解析

本文深入解析了Vivado中XDMA IP核的仿真实战流程,重点剖析了PCIe链路训练状态机(LTSSM)的工作原理与调试方法。通过搭建仿真环境、解读日志与波形,手把手指导如何从配置、链路训练(LTSSM)到BAR映射与DMA启动进行全流程分析与问题定位,帮助工程师掌握核心调试技能,确保PCIe链路稳定与数据传输正确。

weixin_29197051的博客 154

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

TMS320F28377D/F28379D CAN通信避坑指南:从寄存器配置到中断处理的完整流程

本文详细解析了TMS320F28377D/F28379D在CAN通信开发中的关键技术与避坑指南,涵盖时钟配置、寄存器初始化、中断处理等完整流程。针对工业控制和汽车电子应用,提供了实用的优化技巧和错误诊断方法,帮助开发者高效实现稳定可靠的CAN通信。

weixin_30954265的博客 492

Delphi加密解密算法

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

l799623787的专栏 1580

GPU资源池化:技术原理与应用场景全解析

GPU资源池化技术已成为AI时代高效利用算力的关键方案。该技术通过硬件虚拟化、容器化编排和智能调度三个核心层面,实现GPU资源的共享与优化,可将平均利用率从不足30%提升至60-80%。主流方案包括NVIDIA全栈解决方案、云原生Kubernetes生态及开源工具,适用于企业AI平台、大模型训练和边缘推理等场景。虽然面临性能隔离、资源碎片等挑战,但随着硬件虚拟化细化和AI驱动调度算法的发展,GPU池化正向着智能化、自动化方向演进,推动实现"算力如水电"的愿景。

技术引领业务创新 1352

手把手教你学Simulink——基于核能发电系统的场景实例:核电站汽轮机与发电机协调控制仿真

在核电机组中,汽轮机-发电机系统是将核能最终转化为电能的关键环节。与火电机组不同,核反应堆的热惯性大、功率调节慢,因此汽轮机的控制策略需与反应堆特性相匹配,实现安全、稳定、高效的能量转换。维持发电机输出功率/频率稳定(响应电网调度)调节汽轮机进汽压力(匹配一回路蒸汽供应)实现“堆-机协调控制”保障机组在启停、变负荷、甩负荷等工况下的安全性本教程将带你使用构建一个核电站汽轮机与发电机协调控制系统汽轮机调速系统(调门控制)建模发电机与电网接口建模(同步机)

MHD0815的博客 212

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

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

xurunxian的博客 1666

YOLO26全网首发:CVPR2026 FAA| 解决YOLO Neck跨尺度方向冲突--- FAAFusion频域对齐融合模块 | 暴力涨点篇

本文改进:FAAFusion引入YOLO neck ,代替nn.Upsample和Concat

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 644

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

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

芝麻卖瓜的博客 754

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

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

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

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

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

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

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

梦里蓝天 1万+

精雕软件(JDpaint) 5.5 绿色版

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

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、付费专栏及课程。

余额充值