mainform.pas

来自「著名的SecureBlackBox控件完整源码」· PAS 代码 · 共 860 行 · 第 1/2 页

PAS
860
字号
unit MainForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, StdCtrls, ComCtrls,
  {$ifdef DELPHI_NET}
  System.IO,
  System.ComponentModel,
  {$endif}
  EncForm,
  SBUtils, SBConstants, SBAES, SB3DES, SBDES, SBCamellia, SBRC4, SBX509,
  SBPublicKeyCrypto, SBPGPKeys,
  SBXMLCore, SBXMLDefs, SBXMLEnc, SBXMLSec, SBXMLCharsets;

type
  TfrmMain = class(TForm)
    edXMLFile: TEdit;
    btnLoadXML: TButton;
    lbXMLFile: TLabel;
    sbBrowseXMLFile: TSpeedButton;
    btnSaveXML: TButton;
    dlgOpenXML: TOpenDialog;
    tvXML: TTreeView;
    btnEncrypt: TButton;
    btnDecrypt: TButton;
    mmXML: TMemo;
    btnClear: TButton;
    lbNodeType: TLabel;
    dlbNodeType: TLabel;
    btnDelete: TButton;
    lbNamespaceURI: TLabel;
    dlbNamespaceURI: TLabel;
    procedure btnDecryptClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
    procedure btnSaveXMLClick(Sender: TObject);
    procedure btnClearClick(Sender: TObject);
    procedure btnEncryptClick(Sender: TObject);
    procedure tvXMLChange(Sender: TObject; Node: TTreeNode);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnLoadXMLClick(Sender: TObject);
    procedure sbBrowseXMLFileClick(Sender: TObject);
  private
    FXMLDocument: TElXMLDOMDocument;
  public
    procedure LoadCertificate(F: {$ifndef DELPHI_NET}TFileStream{$else}FileStream{$endif};
      const Password: string; X509KeyData: TElXMLKeyInfoX509Data);

    procedure UpdateXML;
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.btnClearClick(Sender: TObject);
begin
  FreeAndNil(FXMLDocument);
  FXMLDocument := TElXMLDOMDocument.Create;
  UpdateXML;
end;

procedure TfrmMain.btnDecryptClick(Sender: TObject);
var
  Decryptor: TElXMLDecryptor;
  SymKeyData, SymKEKData: TElXMLKeyInfoSymmetricData;
  RSAKeyData: TElXMLKeyInfoRSAData;
  X509KeyData: TElXMLKeyInfoX509Data;
{$ifndef SBB_EXCL_XML_PGP}
  PGPKeyData: TElXMLKeyInfoPGPData;
{$endif}
  F: {$ifndef DELPHI_NET}TFileStream{$else}FileStream{$endif};
  Node, T: TElXMLDOMNode;
  i: Integer;
begin
  if Assigned(tvXML.Selected) and
     Assigned(tvXML.Selected.Data) then
    Node := TElXMLDOMNode(tvXML.Selected.Data)
  else
    Node := TElXMLDOMNode(FXMLDocument);

  while (Node is TElXMLDOMElement) and
        (TElXMLDOMElement(Node).LocalName <> 'EncryptedData') and
        Assigned(Node.ParentNode) do
    Node := Node.ParentNode;

  if (Node is TElXMLDOMElement) and
     (TElXMLDOMElement(Node).LocalName = 'EncryptedData') and
     Assigned(Node.ParentNode) and
     (Node.ParentNode is TElXMLDOMDocument) then
    Node := Node.ParentNode;

  if Node is TElXMLDOMDocument then
    T := Node.FirstChild
  else
    T := Node;

  if (not (T is TElXMLDOMElement) or
     (TElXMLDOMElement(T).LocalName <> 'EncryptedData')) then
  begin
    MessageDlg('Please, select EncryptedData element or Document for decryption.', mtInformation, [mbOK], 0);
    Exit;
  end;

  SymKeyData := nil;
  SymKEKData := nil;
  RSAKeyData := nil;
  X509KeyData := nil;
{$ifndef SBB_EXCL_XML_PGP}
  PGPKeyData := nil;
{$endif}
  Decryptor := TElXMLDecryptor.Create(Self);
  try
    try
      if Node is TElXMLDOMDocument then
        Decryptor.Load(TElXMLDOMDocument(Node))
      else
        Decryptor.Load(TElXMLDOMElement(Node));
    except
      on E: Exception do
        raise EXMLError.CreateFmt('Encrypted data loading failed. (%s)', [E.Message]);
    end;

    frmEnc.EncryptKey := Decryptor.EncryptKey;
    frmEnc.EncryptedDataType := Decryptor.EncryptedDataType;
    frmEnc.EncryptionMethod := Decryptor.EncryptionMethod;
    frmEnc.KeyEncryptionType := Decryptor.KeyEncryptionType;
    frmEnc.KeyTransportMethod := Decryptor.KeyTransportMethod;
    frmEnc.KeyWrapMethod := Decryptor.KeyWrapMethod;
    frmEnc.KeyName := Decryptor.KeyName;
    frmEnc.MimeType := Decryptor.MimeType;
    frmEnc.LockOpt := True;
    frmEnc.UpdateOpt;

    while True do
    begin
      if frmEnc.ShowModal = mrOK then
      begin
        if Decryptor.EncryptKey then
        begin
          if Decryptor.KeyEncryptionType = xetKeyWrap then
          begin
            SymKEKData := TElXMLKeyInfoSymmetricData.Create(True);

            {$ifndef DELPHI_NET}
            F := TFileStream.Create(frmEnc.KeyFile, fmOpenRead or fmShareDenyWrite);
            {$else}
            F := FileStream.Create(frmEnc.KeyFile, FileMode.Open, FileAccess.Read);
            {$endif}
            try
              SymKEKData.Key.Load(F);
            finally
              FreeAndNil(F);
            end;

            Decryptor.KeyEncryptionKeyData := SymKEKData;
          end
          else
          begin
            FreeAndNil(RSAKeyData);
            FreeAndNil(X509KeyData);
{$ifndef SBB_EXCL_XML_PGP}
            FreeAndNil(PGPKeyData);
{$endif}
            RSAKeyData := TElXMLKeyInfoRSAData.Create(True);
            RSAKeyData.RSAKeyMaterial.Passphrase := frmEnc.Passphrase;
            X509KeyData := TElXMLKeyInfoX509Data.Create(True);
{$ifndef SBB_EXCL_XML_PGP}
            PGPKeyData := TElXMLKeyInfoPGPData.Create(True);
{$endif}

            {$ifndef DELPHI_NET}
            F := TFileStream.Create(frmEnc.KeyFile, fmOpenRead or fmShareDenyWrite);
            {$else}
            F := FileStream.Create(frmEnc.KeyFile, FileMode.Open, FileAccess.Read);
            {$endif}

            try
              RSAKeyData.RSAKeyMaterial.LoadSecret(F);
            except
            end;

            if not RSAKeyData.RSAKeyMaterial.SecretKey then
            begin
              F.Position := 0;
              LoadCertificate(F, frmEnc.Passphrase, X509KeyData);
            end;

{$ifndef SBB_EXCL_XML_PGP}
            if not RSAKeyData.RSAKeyMaterial.PublicKey and
               not Assigned(X509KeyData.Certificate) then
            begin
              F.Position := 0;
              PGPKeyData.SecretKey := TElPGPSecretKey.Create;
              PGPKeyData.SecretKey.Passphrase := frmEnc.Passphrase;
              try
                PGPKeyData.SecretKey.LoadFromStream(F);
              except
                PGPKeyData.SecretKey.Free;
                PGPKeyData.SecretKey := nil;
              end;
            end;
{$endif}

            FreeAndNil(F);

            if RSAKeyData.RSAKeyMaterial.SecretKey then
              Decryptor.KeyEncryptionKeyData := RSAKeyData
            else
            if Assigned(X509KeyData.Certificate) then
              Decryptor.KeyEncryptionKeyData := X509KeyData
{$ifndef SBB_EXCL_XML_PGP}
            else
            if Assigned(PGPKeyData.SecretKey) then
              Decryptor.KeyEncryptionKeyData := PGPKeyData
{$endif}
            else
              raise EXMLError.Create('Key not loaded.');
          end;
        end
        else
        begin
          SymKeyData := TElXMLKeyInfoSymmetricData.Create(True);

          {$ifndef DELPHI_NET}
          F := TFileStream.Create(frmEnc.KeyFile, fmOpenRead or fmShareDenyWrite);
          {$else}
          F := FileStream.Create(frmEnc.KeyFile, FileMode.Open, FileAccess.Read);
          {$endif}
          try
            SymKeyData.Key.Load(F);
          finally
            FreeAndNil(F);
          end;

          Decryptor.KeyData := SymKeyData;
        end;

        i := Decryptor.Decrypt(FXMLDocument);
        if i <> SB_XML_ENC_ERROR_OK then
        begin
          if (not Decryptor.EncryptKey and (i = SB_XML_ENC_ERROR_INVALID_KEY)) or
             (Decryptor.EncryptKey and (i = SB_XML_ENC_ERROR_INVALID_KEK)) then
            MessageDlg('Decryption failed. Bad key or data is corrupted.', mtError, [mbOK], 0)
          else
            raise EXMLEncError.CreateFmt('Decryption failed. Error code: 0x%x', [i]);

          Continue;
        end;

        if Decryptor.EncryptedDataType = xedtExternal then
        begin
          {$ifndef DELPHI_NET}
          F := TFileStream.Create(frmEnc.ExternalFile, fmCreate);
          {$else}
          F := FileStream.Create(frmEnc.ExternalFile, FileMode.Create, FileAccess.ReadWrite);
          {$endif}
          try
            if Length(Decryptor.DecryptedData) > 0 then
              {$ifndef DELPHI_NET}
              F.Write(Decryptor.DecryptedData[0], Length(Decryptor.DecryptedData));
              {$else}
              F.Write(Decryptor.DecryptedData, 0, Length(Decryptor.DecryptedData));
              {$endif}
          finally
            FreeAndNil(F);
          end;

          MessageDlg('Data saved successfully.', mtInformation, [mbOK], 0);
        end
        else
        begin
          if Assigned(Decryptor.DecryptedNode) then
          begin
            if Node is TElXMLDOMDocument then
              FXMLDocument.ReplaceChild(Decryptor.DecryptedNode, FXMLDocument.FirstChild)
            else
              Node.ParentNode.ReplaceChild(Decryptor.DecryptedNode, Node);

            Decryptor.DecryptedNode := nil;
          end
          else
          if (Decryptor.EncryptedDataType = xedtContent) and
             Assigned(Decryptor.DecryptedNodeList) then
          begin
            T := Node.ParentNode;
            for i := 0 to Decryptor.DecryptedNodeList.Length - 1 do
              T.InsertBefore(Decryptor.DecryptedNodeList.Item[i].CloneNode(True), Node);

            T.RemoveChild(Node);
          end;

          UpdateXML;
        end;

        Break;
      end
      else
        Break;
    end;

  finally
    FreeAndNil(Decryptor);
    FreeAndNil(SymKeyData);
    FreeAndNil(SymKEKData);
    FreeAndNil(RSAKeyData);
    FreeAndNil(X509KeyData);
{$ifndef SBB_EXCL_XML_PGP}
    FreeAndNil(PGPKeyData);
{$endif}
  end;
end;

procedure TfrmMain.btnDeleteClick(Sender: TObject);
var
  N: TElXMLDOMNode;
begin
  if Assigned(tvXML.Selected) and
     Assigned(tvXML.Selected.Data) then
  begin
    N := TElXMLDOMNode(tvXML.Selected.Data);
    if (N is TElXMLDOMElement) or
       (N is TElXMLDOMText) then
    begin
      if Assigned(N.ParentNode) then
        N.ParentNode.RemoveChild(N)
      else
        FXMLDocument.RemoveChild(N);
    end
    else
    if (N is TElXMLDOMAttr) and Assigned(tvXML.Selected.Parent)
       and Assigned(tvXML.Selected.Parent.Data) and
       (TElXMLDOMNode(tvXML.Selected.Parent.Data) is TElXMLDOMElement) then
      TElXMLDOMElement(tvXML.Selected.Parent.Data).RemoveAttributeNode(TElXMLDOMAttr(N));
  end;

  UpdateXML;
end;

procedure TfrmMain.btnEncryptClick(Sender: TObject);
var
  Encryptor: TElXMLEncryptor;
  SymKeyData, SymKEKData: TElXMLKeyInfoSymmetricData;
  RSAKeyData: TElXMLKeyInfoRSAData;
  X509KeyData: TElXMLKeyInfoX509Data;
{$ifndef SBB_EXCL_XML_PGP}
  PGPKeyData: TElXMLKeyInfoPGPData;
{$endif}
  F: {$ifndef DELPHI_NET}TFileStream{$else}FileStream{$endif};
  Node, EncNode: TElXMLDOMNode;
  Buf: ByteArray;
begin
  SymKeyData := nil;
  SymKEKData := nil;
  RSAKeyData := nil;
  X509KeyData := nil;
{$ifndef SBB_EXCL_XML_PGP}
  PGPKeyData := nil;
{$endif}
  frmEnc.LockOpt := False;
  if frmEnc.ShowModal = mrOK then
  begin
    Encryptor := TElXMLEncryptor.Create(Self);
    try
       Encryptor.EncryptKey := frmEnc.EncryptKey;
       Encryptor.EncryptionMethod := frmEnc.EncryptionMethod;
       Encryptor.KeyName := frmEnc.KeyName;
       Encryptor.EncryptedDataType := frmEnc.EncryptedDataType;
       if Encryptor.EncryptKey then
       begin
         Encryptor.KeyEncryptionType := frmEnc.KeyEncryptionType;
         Encryptor.KeyTransportMethod := frmEnc.KeyTransportMethod;
         Encryptor.KeyWrapMethod := frmEnc.KeyWrapMethod;

         SymKeyData := TElXMLKeyInfoSymmetricData.Create(True);
         // generate random Key & IV
         case Encryptor.EncryptionMethod of
           xem3DES:
           begin
             SymKeyData.Key.Generate(T3DESKeySize * 8);
             SymKeyData.Key.GenerateIV(8 * 8);
           end;

           xemAES:
           begin
             SymKeyData.Key.Generate(SizeOf(TAESKey256) * 8);
             SymKeyData.Key.GenerateIV(16 * 8);
           end;

           xemCamellia:
           begin
             SymKeyData.Key.Generate(32 * 8); // 16, 24, 32
             SymKeyData.Key.GenerateIV(16 * 8);
           end;

           xemDES:
           begin
             SymKeyData.Key.Generate(TDESKeySize * 8);
             SymKeyData.Key.GenerateIV(8 * 8);
           end;

           xemRC4:
           begin
             SymKeyData.Key.Generate(16 * 8); // 1..32
           end;
         end;

         Encryptor.KeyData := SymKeyData;

         if Encryptor.KeyEncryptionType = xetKeyWrap then
         begin
           SymKEKData := TElXMLKeyInfoSymmetricData.Create(True);

           {$ifndef DELPHI_NET}
           F := TFileStream.Create(frmEnc.KeyFile, fmOpenRead or fmShareDenyWrite);
           {$else}
           F := FileStream.Create(frmEnc.KeyFile, FileMode.Open, FileAccess.Read);
           {$endif}
           try
             SymKEKData.Key.Load(F);
           finally
             FreeAndNil(F);
           end;

           Encryptor.KeyEncryptionKeyData := SymKEKData;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?