📄 lbasym.pas
字号:
(* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TurboPower LockBox
*
* The Initial Developer of the Original Code is
* TurboPower Software
*
* Portions created by the Initial Developer are Copyright (C) 1997-2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** *)
{*********************************************************}
{* LBASYM.PAS 2.07 *}
{* Copyright (c) 2002 TurboPower Software Co *}
{* All rights reserved. *}
{*********************************************************}
{$I LockBox.inc}
unit LbAsym;
{-Asymmetric key encryption classes}
interface
uses
Classes, SysUtils, LbBigInt, LbClass, LbConst;
type
pByte = ^Byte;
type
TLbAsymKeySize = (aks128, aks256, aks512, aks768, aks1024);
const
cLbDefAsymKeySize = aks512;
cLbAsymKeyBytes : array[TLbAsymKeySize] of Word =
(cBytes128, cBytes256, cBytes512, cBytes768, cBytes1024);
type
TLbProgressEvent = procedure(Sender : TObject; var Abort : Boolean) of object;
{ TLbAsymmetricKey }
type
TLbAsymmetricKey = class
protected {private}
FKeySize : TLbAsymKeySize;
FPassphrase : string;
procedure SetKeySize(Value : TLbAsymKeySize); virtual;
{!!.06}
procedure MovePtr(var Ptr : PByte; var Max : Integer );
procedure MovePtrCount(var Ptr : PByte; var Max : Integer; Count : Integer);
function GetASN1StructLen( var input : pByte; var len : Integer ) : Integer;
function GetASN1StructNum ( var input : pByte; var len : Integer ) : Integer;
procedure CreateASN1(var Buf; var BufLen : Integer; Tag : Byte);
procedure ParseASN1(var input : pByte; var length : Integer; biValue : TLbBigInt);
function EncodeASN1(biValue : TLbBigInt; var pBuf : PByteArray; var MaxLen : Integer) : Integer;
function CreateASNKey(Input : pByteArray; Length : Integer) : Integer; virtual; abstract;
function ParseASNKey(Input : pByte; Length : Integer) : boolean; virtual; abstract;
{!!.06}
public {methods}
constructor Create(aKeySize : TLbAsymKeySize); virtual;
destructor Destroy; override;
procedure Assign(aKey : TLbAsymmetricKey); virtual;
{!!.06}
procedure LoadFromStream(aStream : TStream); virtual; { as ASN.1 set }
procedure StoreToStream(aStream : TStream); virtual; { as ASN.1 set }
procedure LoadFromFile(aFileName : string); virtual; { as ASN.1 set }
procedure StoreToFile(aFileName : string); virtual; { as ASN.1 set }
{!!.06}
public {properties}
property KeySize : TLbAsymKeySize
read FKeySize write SetKeySize;
property Passphrase : string
read FPassphrase write FPassphrase;
end;
{ TLbAsymmetricCipher }
type
TLbAsymmetricCipher = class(TLbCipher)
protected {private}
FKeySize : TLbAsymKeySize;
FOnProgress : TLbProgressEvent;
procedure SetKeySize(Value : TLbAsymKeySize); virtual;
public {methods}
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
procedure GenerateKeyPair; virtual; abstract;
public {properties}
property KeySize : TLbAsymKeySize
read FKeySize write SetKeySize;
property OnProgress : TLbProgressEvent
read FOnProgress write FOnProgress;
end;
{ TLbSignature }
type
TLbSignature = class(TLbBaseComponent)
protected {private}
FKeySize : TLbAsymKeySize;
FOnProgress : TLbProgressEvent;
procedure SetKeySize(Value : TLbAsymKeySize); virtual;
public {methods}
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
procedure GenerateKeyPair; virtual; abstract;
procedure SignBuffer(const Buf; BufLen : Cardinal); virtual; abstract;
procedure SignFile(const AFileName : string); virtual; abstract;
procedure SignStream(AStream : TStream); virtual; abstract;
procedure SignString(const AStr : string); virtual; abstract;
function VerifyBuffer(const Buf; BufLen : Cardinal) : Boolean; virtual; abstract;
function VerifyFile(const AFileName : string) : Boolean; virtual; abstract;
function VerifyStream(AStream : TStream) : Boolean; virtual; abstract;
function VerifyString(const AStr : string) : Boolean; virtual; abstract;
public {properties}
property KeySize : TLbAsymKeySize
read FKeySize write SetKeySize;
property OnProgress : TLbProgressEvent
read FOnProgress write FOnProgress;
end;
implementation
uses
LbCipher, LbProc, LbUtils;
{ == TLbAsymmetricKey ====================================================== }
constructor TLbAsymmetricKey.Create(aKeySize : TLbAsymKeySize);
begin
FKeySize := aKeySize;
end;
{ -------------------------------------------------------------------------- }
destructor TLbAsymmetricKey.Destroy;
begin
inherited Destroy;
end;
{ -------------------------------------------------------------------------- }
procedure TLbAsymmetricKey.Assign(aKey : TLbAsymmetricKey);
begin
FKeySize := aKey.KeySize;
end;
{ -------------------------------------------------------------------------- }
procedure TLbAsymmetricKey.SetKeySize(Value : TLbAsymKeySize);
begin
FKeySize := Value;
end;
{ -------------------------------------------------------------------------- }
{!!.06}
procedure TLbAsymmetricKey.MovePtr(var Ptr : PByte; var Max : Integer);
{ increment buffer pointer and decrement Max }
begin
Dec(Max);
if (Max < 0) then
raise Exception.Create(sASNKeyBadKey);
Inc(Ptr);
end;
{ -------------------------------------------------------------------------- }
{!!.06}
procedure TLbAsymmetricKey.MovePtrCount(var Ptr : PByte; var Max : Integer;
Count : Integer);
{ increment buffer pointer and decrement Max by Count bytes }
begin
Dec(Max, Count);
if (Max < 0) then
raise Exception.Create(sASNKeyBadKey);
Inc(Ptr, Count);
end;
{ -------------------------------------------------------------------------- }
{!!.06}
function TLbAsymmetricKey.GetASN1StructLen(var Input : PByte; var Len : Integer) : Integer;
{ return length of ASN.1 structure in buffer located at Input }
var
Tmp_int : Integer;
TagLen : Integer;
Tmp_ptr : PByte;
Max : Integer;
IsHighBit : boolean;
begin
Max := Len;
Tmp_ptr := Input;
tagLen := $00;
isHighBit := ( tmp_ptr^ and HIGH_BIT_MASK ) = HIGH_BIT_MASK;
tmp_int := tmp_ptr^ and BIT_MASK_7F;
MovePtr( tmp_ptr, max );
if( isHighBit )then begin
while( tmp_int > 0 )do begin
tagLen := ( tagLen shl 8 ) or tmp_ptr^;
MovePtr( tmp_ptr, max );
dec( tmp_int );
end;
end else
tagLen := tmp_int;
result := tagLen;
len := max;
input := tmp_ptr;
end;
{ -------------------------------------------------------------------------- }
{!!.06}
function TLbAsymmetricKey.GetASN1StructNum (var Input : PByte; var Len : Integer) : Integer;
{ return ID of ASN.1 structure in buffer located at Input }
var
tmp_int : Integer;
tagNum : Integer;
tmp_ptr : pBYTE;
max : Integer;
hold_byte : BYTE;
tag : Integer;
begin
max := len;
tmp_ptr := input;
hold_byte := tmp_ptr^;
tagNum := ( hold_byte and ASN1_TAG_NUM_MASK );
if( tagNum = ASN1_TYPE_HIGH_TAG_NUMBER )then begin
MovePtr( tmp_ptr, max );
tmp_int := 0;
while(( tmp_ptr^ and HIGH_BIT_MASK ) > 0 )do begin
tmp_int := tmp_int shl 7;
MovePtr( tmp_ptr, max );
tmp_int := tmp_int or ( tmp_ptr^ and BIT_MASK_7F );
end;
tmp_int := tmp_int shl 7;
MovePtr( tmp_ptr, max );
tmp_int := tmp_int or ( tmp_ptr^ and BIT_MASK_7F );
tag := tmp_int;
end else begin
tag := tagNum;
MovePtr( tmp_ptr, max );
end;
len := max;
input := tmp_ptr;
result := tag;
end;
{ -------------------------------------------------------------------------- }
{!!.06}
procedure TLbAsymmetricKey.CreateASN1(var Buf; var BufLen : Integer; Tag : Byte);
{ create an ASN.1 format buffer }
var
i : Integer;
x : Integer;
tmp : array[0..4095] of Byte;
TagSize : Integer;
tmp_Len : Integer;
begin
if (BufLen > SizeOf(tmp)) then
raise Exception.Create(sASNKeyBadKey);
TagSize := 0;
tmp_Len := BufLen;
tmp[TagSize] := Tag;
Inc(TagSize);
if (BufLen > BIT_MASK_7F) then begin
i := BufLen div $FF;
if (i = 0) then
i := 1;
tmp[TagSize] := ($80 or i);
Inc(TagSize , i);
for x := 1 to i do begin
tmp[TagSize] := BufLen and $000000FF;
BufLen := BufLen shr 8;
Dec(TagSize);
end;
Inc(TagSize, i+1);
end else begin
tmp[TagSize] := BufLen;
Inc(TagSize)
end;
BufLen := tmp_Len + TagSize;
if (BufLen > SizeOf(tmp)) then
raise Exception.Create(sASNKeyBadKey);
Move(Buf, tmp[TagSize], tmp_Len);
Move(tmp, Buf, BufLen);
end;
{ -------------------------------------------------------------------------- }
{!!.06}
function TLbAsymmetricKey.EncodeASN1(biValue : TLbBigInt; var pBuf : PByteArray;
var MaxLen : Integer) : Integer;
const
TAG02 = $02;
var
Pad : Boolean;
begin
Result := biValue.Size;
Pad := (biValue.GetByteValue(1) > $80);
if Pad then
Inc(Result);
if (Result > MaxLen) then
raise Exception.Create(sASNKeyBadKey);
FillChar(pBuf^, Result, #0);
biValue.ToBuffer(pBuf^, Result);
if Pad then begin
Move(pBuf^[0], pBuf^[1], Result-1);
pBuf^[0] := $00;
end;
CreateASN1(pBuf^, Result, TAG02);
MovePtrCount(PByte(pBuf), MaxLen, Result);
end;
{ -------------------------------------------------------------------------- }
{!!.06}
procedure TLbAsymmetricKey.LoadFromStream(aStream : TStream);
{ load key from ASN.1 format stream (decrypt if necessary) }
var
KeyBuf : array[0..4096] of Byte;
Len : Integer;
MemStream : TMemoryStream;
BFKey : TKey128;
begin
FillChar(KeyBuf, SizeOf(KeyBuf), #0);
aStream.Position := 0;
{ decrypt stream first if passphrase in not empty }
if (FPassphrase <> '') then begin
MemStream := TMemoryStream.Create;
try
StringHashMD5(TMD5Digest(BFKey), FPassphrase);
BFEncryptStream(aStream, MemStream, BFKey, False);
Len := MemStream.Size;
if (Len > SizeOf(KeyBuf)) then
raise Exception.Create(sASNKeyBadKey);
MemStream.Position := 0;
MemStream.Read(KeyBuf, Len);
finally
MemStream.Free;
end;
end else begin
Len := aStream.Size;
if (Len > SizeOf(KeyBuf)) then
raise Exception.Create(sASNKeyBadKey);
aStream.Read(KeyBuf, Len);
end;
ParseASNKey(pByte(@KeyBuf), Len);
FillChar(KeyBuf, SizeOf(KeyBuf), #0);
end;
{ -------------------------------------------------------------------------- }
{!!.06}
procedure TLbAsymmetricKey.StoreToStream(aStream : TStream);
{ save key to ASN.1 format stream (encrypt if necessary) }
var
KeyBuf : array[0..4096] of Byte;
Len : Integer;
MemStream : TMemoryStream;
BFKey : TKey128;
begin
FillChar(KeyBuf, SizeOf(KeyBuf), #0);
Len := CreateASNKey(@KeyBuf, SizeOf(KeyBuf));
{ encrypt buffer first if passphrase in not empty }
if (FPassphrase <> '') then begin
MemStream := TMemoryStream.Create;
try
MemStream.Write(KeyBuf, Len);
MemStream.Position := 0;
StringHashMD5(TMD5Digest(BFKey), FPassphrase);
BFEncryptStream(MemStream, aStream, BFKey, True);
finally
MemStream.Free;
end;
end else
aStream.Write(KeyBuf, Len);
FillChar(KeyBuf, SizeOf(KeyBuf), #0);
end;
{ -------------------------------------------------------------------------- }
{!!.06}
procedure TLbAsymmetricKey.LoadFromFile(aFileName : string);
{ load key from ASN.1 format file (decrypt if necessary) }
var
FS : TFileStream;
begin
FS := TFileStream.Create(aFileName, fmOpenRead);
try
LoadFromStream(FS);
finally
FS.Free;
end;
end;
{ -------------------------------------------------------------------------- }
{!!.06}
procedure TLbAsymmetricKey.StoreToFile(aFileName : string);
{ save key to ASN.1 format file (encrypt if necessary) }
var
FS : TFileStream;
begin
FS := TFileStream.Create(aFileName, fmCreate);
try
StoreToStream(FS);
finally
FS.Free;
end;
end;
{ -------------------------------------------------------------------------- }
{!!.06}
procedure TLbAsymmetricKey.ParseASN1(var input : pByte; var length : Integer;
biValue : TLbBigInt);
var
tag : Integer;
len : Integer;
begin
tag := GetASN1StructNum( input, length );
len := GetASN1StructLen( input, length );
if( len > length )then
raise Exception.Create(sASNKeyBadKey);
if( tag = ASN1_TYPE_Integer )then begin
if( input^ = $00 ) and ( pByteArray( input )^[ 1 ] > $80 )then begin
MovePtr( input, length );
dec( len );
end;
biValue.CopyBuffer( input^, len );
inc( pChar( input ), len );
length := length - len;
end else
raise Exception.Create(sASNKeyBadKey);
end;
{ == TLbAsymmetricCipher =================================================== }
constructor TLbAsymmetricCipher.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
FKeySize := cLbDefAsymKeySize;
end;
{ -------------------------------------------------------------------------- }
destructor TLbAsymmetricCipher.Destroy;
begin
inherited Destroy;
end;
{ -------------------------------------------------------------------------- }
procedure TLbAsymmetricCipher.SetKeySize(Value : TLbAsymKeySize);
begin
FKeySize := Value;
end;
{ == TLbSignature ========================================================== }
constructor TLbSignature.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
FKeySize := cLbDefAsymKeySize;
end;
{ -------------------------------------------------------------------------- }
destructor TLbSignature.Destroy;
begin
inherited Destroy;
end;
{ -------------------------------------------------------------------------- }
procedure TLbSignature.SetKeySize(Value : TLbAsymKeySize);
begin
FKeySize := Value;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -