|
@@ -27,7 +27,6 @@ uses
|
|
|
SysUtils,
|
|
|
TypInfo,
|
|
|
uregexpr,
|
|
|
- UAccounts,
|
|
|
UCommon,
|
|
|
UCrypto,
|
|
|
UEncoding;
|
|
@@ -43,76 +42,87 @@ type
|
|
|
BadExtendedChecksum
|
|
|
);
|
|
|
|
|
|
- { PayloadType}
|
|
|
-
|
|
|
- PayloadType = (
|
|
|
- NonDeterministic = 0, // Payload encryption and encoding method not specified.
|
|
|
- &Public = 1, // Unencrypted, public payload.
|
|
|
- RecipientKeyEncrypted = 2, // ECIES encrypted using recipient accounts public key.
|
|
|
- SenderKeyEncrypted = 3, // ECIES encrypted using sender accounts public key.
|
|
|
- PasswordEncrypted = 4, // AES encrypted using pwd param
|
|
|
- AsciiFormatted = 5, // Payload data encoded in ASCII
|
|
|
- HexFormatted = 6, // Payload data encoded in HEX
|
|
|
- Base58Formatted = 7, // Payload data encoded in Base58
|
|
|
- AddressedByName = 8 // E-PASA addressed by account name (not number).
|
|
|
+ { TPayloadTrait }
|
|
|
+
|
|
|
+ TPayloadTrait = (
|
|
|
+ ptNonDeterministic = 0, // Payload encryption and encoding method not specified.
|
|
|
+ ptPublic = 1, // Unencrypted, public payload.
|
|
|
+ ptRecipientKeyEncrypted = 2, // ECIES encrypted using recipient accounts public key.
|
|
|
+ ptSenderKeyEncrypted = 3, // ECIES encrypted using sender accounts public key.
|
|
|
+ ptPasswordEncrypted = 4, // AES encrypted using pwd param
|
|
|
+ ptAsciiFormatted = 5, // Payload data encoded in ASCII
|
|
|
+ ptHexFormatted = 6, // Payload data encoded in HEX
|
|
|
+ ptBase58Formatted = 7, // Payload data encoded in Base58
|
|
|
+ ptAddressedByName = 8 // E-PASA addressed by account name (not number).
|
|
|
);
|
|
|
|
|
|
- { PayloadTypeHelper }
|
|
|
+ { TPayloadTraitHelper }
|
|
|
|
|
|
- PayloadTypeHelper = record helper for PayloadType
|
|
|
+ TPayloadTraitHelper = record helper for TPayloadTrait
|
|
|
public
|
|
|
- function Value: Int32;
|
|
|
+ function ProtocolValue: byte;
|
|
|
end;
|
|
|
|
|
|
- { PayloadTypes }
|
|
|
+ { TPayloadType }
|
|
|
|
|
|
- PayloadTypes = set of PayloadType;
|
|
|
+ TPayloadType = set of TPayloadTrait;
|
|
|
|
|
|
- { PayloadTypesHelper }
|
|
|
+ { TPayloadTypesHelper }
|
|
|
|
|
|
- PayloadTypesHelper = record helper for PayloadTypes
|
|
|
+ TPayloadTypeHelper = record helper for TPayloadType
|
|
|
public
|
|
|
- function IsPayloadTypeInSet(APayloadType: PayloadType): Boolean; inline;
|
|
|
+ function HasTrait(APayloadTrait: TPayloadTrait): Boolean; inline;
|
|
|
+ function ProtocolValue : byte;
|
|
|
end;
|
|
|
|
|
|
-
|
|
|
{ TEPasa }
|
|
|
|
|
|
+
|
|
|
TEPasa = record
|
|
|
strict private
|
|
|
var
|
|
|
FAccount, FAccountChecksum: TNullable<UInt32>;
|
|
|
FAccountName, FPayload, FPassword, FExtendedChecksum: String;
|
|
|
- FPayloadTypes: PayloadTypes;
|
|
|
+ FPayloadType: TPayloadType;
|
|
|
|
|
|
function GetAccount: TNullable<UInt32>; inline;
|
|
|
procedure SetAccount(const AValue: TNullable<UInt32>); inline;
|
|
|
function GetAccountChecksum: TNullable<UInt32>; inline;
|
|
|
procedure SetAccountChecksum(const AValue: TNullable<UInt32>); inline;
|
|
|
- function GetPayloadTypes: PayloadTypes; inline;
|
|
|
+ function GetPayloadType: TPayloadType; inline;
|
|
|
function GetAccountName: String; inline;
|
|
|
procedure SetAccountName(const AValue: String); inline;
|
|
|
- procedure SetPayloadTypes(const AValue: PayloadTypes); inline;
|
|
|
+ procedure SetPayloadType(const AValue: TPayloadType); inline;
|
|
|
function GetExtendedChecksum: String; inline;
|
|
|
procedure SetExtendedChecksum(const AValue: String); inline;
|
|
|
function GetPassword: String; inline;
|
|
|
procedure SetPassword(const AValue: String); inline;
|
|
|
function GetPayload: String; inline;
|
|
|
procedure SetPayload(const AValue: String); inline;
|
|
|
-
|
|
|
+ function GetHasPayload: Boolean; inline;
|
|
|
+ function GetIsStandard: Boolean; inline;
|
|
|
+ function GetIsPayToKey: Boolean; inline;
|
|
|
+ function GetIsAddressedByName : Boolean; inline;
|
|
|
+ function GetIsAddressedByNumber : Boolean; inline;
|
|
|
+ class function GetEmptyValue : TEPasa; static;
|
|
|
public
|
|
|
- function IsPayToKey: Boolean; inline;
|
|
|
- function GetRawPayloadBytes(): TArray<Byte>; inline;
|
|
|
- function ToString(): String; overload;
|
|
|
- function ToString(AOmitExtendedChecksum: Boolean): String; overload;
|
|
|
-
|
|
|
property Account: TNullable<UInt32> read GetAccount write SetAccount;
|
|
|
property AccountChecksum: TNullable<UInt32> read GetAccountChecksum write SetAccountChecksum;
|
|
|
property AccountName: String read GetAccountName write SetAccountName;
|
|
|
- property PayloadTypes: PayloadTypes read GetPayloadTypes write SetPayloadTypes;
|
|
|
+ property PayloadType: TPayloadType read GetPayloadType write SetPayloadType;
|
|
|
property Payload: String read GetPayload write SetPayload;
|
|
|
property Password: String read GetPassword write SetPassword;
|
|
|
property ExtendedChecksum: String read GetExtendedChecksum write SetExtendedChecksum;
|
|
|
+ property IsAddressedByNumber: boolean read GetIsAddressedByNumber;
|
|
|
+ property IsAddressedByName: boolean read GetIsAddressedByName;
|
|
|
+ property IsPayToKey: boolean read GetIsPayToKey;
|
|
|
+ property IsStandard: boolean read GetIsStandard;
|
|
|
+ property HasPayload: boolean read GetHasPayload;
|
|
|
+ class property Empty : TEPasa read GetEmptyValue;
|
|
|
+
|
|
|
+ function GetRawPayloadBytes(): TArray<Byte>; inline;
|
|
|
+ function ToString(): String; overload;
|
|
|
+ function ToString(AOmitExtendedChecksum: Boolean): String; overload;
|
|
|
|
|
|
class function TryParse(const AEPasaText: String; out AEPasa: TEPasa) : Boolean; static;
|
|
|
class function Parse(const AEPasaText: String): TEPasa; static;
|
|
@@ -121,6 +131,8 @@ type
|
|
|
|
|
|
end;
|
|
|
|
|
|
+
|
|
|
+
|
|
|
{ TEPasaParser }
|
|
|
|
|
|
TEPasaParser = class
|
|
@@ -155,9 +167,9 @@ type
|
|
|
function TryParse(const AEPasaText: String; out AEPasa: TEPasa; out AErrorCode: EPasaErrorCode): Boolean; overload;
|
|
|
end;
|
|
|
|
|
|
- { TEPasaHelper }
|
|
|
+ { TEPasaComp }
|
|
|
|
|
|
- TEPasaHelper = class sealed(TObject)
|
|
|
+ TEPasaComp = class sealed(TObject)
|
|
|
|
|
|
strict private
|
|
|
class function ReadUInt16AsBytesLE(AValue: UInt16): TArray<Byte>; static;
|
|
@@ -177,9 +189,11 @@ type
|
|
|
|
|
|
class function ComputeExtendedChecksum(const AText: String): String; static;
|
|
|
class function IsValidExtendedChecksum(const AText: String; const AChecksum: String): Boolean; static;
|
|
|
- class function IsValidPayloadLength(APayloadType: PayloadTypes; const APayloadContent: String): Boolean; static;
|
|
|
+ class function IsValidPayloadLength(APayloadType: TPayloadType; const APayloadContent: String): Boolean; static;
|
|
|
class function IsValidPasswordLength(const APasswordValue: String) : Boolean; static;
|
|
|
|
|
|
+ class function GetPayloadTypeProtocolByte(const APayloadType : TPayloadType) : Byte;
|
|
|
+ class function GetPayloadTypeFromProtocolByte(AByte : Byte) : TPayloadType;
|
|
|
end;
|
|
|
|
|
|
resourcestring
|
|
@@ -200,30 +214,40 @@ uses
|
|
|
HlpConverters,
|
|
|
UMemory;
|
|
|
|
|
|
-{ PayloadTypeHelper }
|
|
|
+var
|
|
|
+ EmptyEPasa : TEPasa;
|
|
|
+
|
|
|
+{ TPayloadTraitHelper }
|
|
|
|
|
|
-function PayloadTypeHelper.Value: Int32;
|
|
|
+function TPayloadTraitHelper.ProtocolValue: Byte;
|
|
|
begin
|
|
|
case Self of
|
|
|
- NonDeterministic: Result := $00000000;
|
|
|
- &Public: Result := $00000001;
|
|
|
- RecipientKeyEncrypted: Result := $00000010;
|
|
|
- SenderKeyEncrypted: Result := $00000100;
|
|
|
- PasswordEncrypted: Result := $00001000;
|
|
|
- AsciiFormatted: Result := $00010000;
|
|
|
- HexFormatted: Result := $00100000;
|
|
|
- Base58Formatted: Result := $01000000;
|
|
|
- AddressedByName: Result := $10000000;
|
|
|
+ ptNonDeterministic: Result := 0;
|
|
|
+ ptPublic: Result := BYTE_BIT_0;
|
|
|
+ ptRecipientKeyEncrypted: Result := BYTE_BIT_1;
|
|
|
+ ptSenderKeyEncrypted: Result := BYTE_BIT_2;
|
|
|
+ ptPasswordEncrypted: Result := BYTE_BIT_3;
|
|
|
+ ptAsciiFormatted: Result := BYTE_BIT_4;
|
|
|
+ ptHexFormatted: Result := BYTE_BIT_5;
|
|
|
+ ptBase58Formatted: Result := BYTE_BIT_6;
|
|
|
+ ptAddressedByName: Result := BYTE_BIT_7;
|
|
|
end;
|
|
|
+ raise Exception.Create('Internal Error 2faed11a-1b0f-447a-87d1-2e1735ac4ca2');
|
|
|
end;
|
|
|
|
|
|
-{ PayloadTypesHelper }
|
|
|
+{ TPayloadTypeHelper }
|
|
|
+
|
|
|
+function TPayloadTypeHelper.HasTrait(APayloadTrait : TPayloadTrait) : Boolean;
|
|
|
+begin
|
|
|
+ Result := APayloadTrait in Self;
|
|
|
+end;
|
|
|
|
|
|
-function PayloadTypesHelper.IsPayloadTypeInSet(APayloadType : PayloadType) : Boolean;
|
|
|
+function TPayloadTypeHelper.ProtocolValue : Byte;
|
|
|
begin
|
|
|
- Result := APayloadType in Self;
|
|
|
+ Result := TEPasaComp.GetPayloadTypeProtocolByte(Self);
|
|
|
end;
|
|
|
|
|
|
+
|
|
|
{ TEPasa }
|
|
|
|
|
|
function TEPasa.GetAccount: TNullable<UInt32>;
|
|
@@ -256,9 +280,9 @@ begin
|
|
|
Result := FPayload;
|
|
|
end;
|
|
|
|
|
|
-function TEPasa.GetPayloadTypes: PayloadTypes;
|
|
|
+function TEPasa.GetPayloadType: TPayloadType;
|
|
|
begin
|
|
|
- Result := FPayloadTypes;
|
|
|
+ Result := FPayloadType;
|
|
|
end;
|
|
|
|
|
|
procedure TEPasa.SetAccount(const AValue: TNullable<UInt32>);
|
|
@@ -291,29 +315,50 @@ begin
|
|
|
FPayload := AValue;
|
|
|
end;
|
|
|
|
|
|
-procedure TEPasa.SetPayloadTypes(const AValue: PayloadTypes);
|
|
|
+procedure TEPasa.SetPayloadType(const AValue: TPayloadType);
|
|
|
+begin
|
|
|
+ FPayloadType := AValue;
|
|
|
+end;
|
|
|
+
|
|
|
+function TEPasa.GetIsAddressedByNumber : Boolean;
|
|
|
+begin
|
|
|
+ Result := NOT PayloadType.HasTrait(ptAddressedByName);
|
|
|
+end;
|
|
|
+
|
|
|
+function TEPasa.GetIsAddressedByName : Boolean;
|
|
|
begin
|
|
|
- FPayloadTypes := AValue;
|
|
|
+ Result := (NOT IsPayToKey) AND PayloadType.HasTrait(ptAddressedByName);
|
|
|
end;
|
|
|
|
|
|
-function TEPasa.IsPayToKey: Boolean;
|
|
|
+function TEPasa.GetIsPayToKey: Boolean;
|
|
|
begin
|
|
|
Result :=
|
|
|
(AccountName = '@') and
|
|
|
- (PayloadTypes.IsPayloadTypeInSet(PayloadType.AddressedByName) and
|
|
|
- PayloadTypes.IsPayloadTypeInSet(PayloadType.Public) and
|
|
|
- PayloadTypes.IsPayloadTypeInSet(PayloadType.Base58Formatted));
|
|
|
+ (PayloadType.HasTrait(ptAddressedByName) and
|
|
|
+ PayloadType.HasTrait(ptPublic) and
|
|
|
+ PayloadType.HasTrait(ptBase58Formatted));
|
|
|
+end;
|
|
|
+
|
|
|
+function TEPasa.GetIsStandard: Boolean;
|
|
|
+begin
|
|
|
+ Result := (NOT PayloadType.HasTrait(ptAddressedByName)) AND (NOT HasPayload);
|
|
|
+end;
|
|
|
+
|
|
|
+function TEPasa.GetHasPayload: Boolean;
|
|
|
+begin
|
|
|
+ Result := PayloadType.HasTrait(ptPublic) OR PayloadType.HasTrait(ptRecipientKeyEncrypted) OR PayloadType.HasTrait(ptSenderKeyEncrypted);
|
|
|
end;
|
|
|
|
|
|
+
|
|
|
function TEPasa.GetRawPayloadBytes: TArray<Byte>;
|
|
|
begin
|
|
|
- if (PayloadTypes.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then
|
|
|
+ if (PayloadType.HasTrait(ptAsciiFormatted)) then
|
|
|
Exit(TEncoding.ASCII.GetBytes(Payload));
|
|
|
|
|
|
- if (PayloadTypes.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then
|
|
|
+ if (PayloadType.HasTrait(ptBase58Formatted)) then
|
|
|
Exit(TPascalBase58Encoding.Decode(Payload));
|
|
|
|
|
|
- if (PayloadTypes.IsPayloadTypeInSet(PayloadType.HexFormatted)) then
|
|
|
+ if (PayloadType.HasTrait(ptHexFormatted)) then
|
|
|
Exit(THexEncoding.Decode(Payload));
|
|
|
|
|
|
raise EPascalCoinException.CreateRes(@SUnknownPayloadEncoding);
|
|
@@ -324,7 +369,7 @@ var
|
|
|
LPayloadContent: String;
|
|
|
begin
|
|
|
Result := string.Empty;
|
|
|
- if (PayloadTypes.IsPayloadTypeInSet(PayloadType.AddressedByName)) then begin
|
|
|
+ if (PayloadType.HasTrait(ptAddressedByName)) then begin
|
|
|
Result := Result + TPascal64Encoding.Escape(AccountName);
|
|
|
end else begin
|
|
|
Result := Result + Account.Value.ToString();
|
|
@@ -333,24 +378,24 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
- if (PayloadTypes.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then begin
|
|
|
+ if (PayloadType.HasTrait(ptAsciiFormatted)) then begin
|
|
|
LPayloadContent := String.Format('"%s"', [TPascalAsciiEncoding.Escape(Payload)]);
|
|
|
- end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.HexFormatted)) then begin
|
|
|
+ end else if (PayloadType.HasTrait(ptHexFormatted)) then begin
|
|
|
LPayloadContent := string.Format('0x%s', [Payload]);
|
|
|
- end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then begin
|
|
|
+ end else if (PayloadType.HasTrait(ptBase58Formatted)) then begin
|
|
|
LPayloadContent := string.Format('%s', [Payload]);
|
|
|
end else begin
|
|
|
// it is non-deterministic, so payload content is ignored
|
|
|
LPayloadContent := string.Empty;
|
|
|
end;
|
|
|
|
|
|
- if (PayloadTypes.IsPayloadTypeInSet(PayloadType.Public)) then begin
|
|
|
+ if (PayloadType.HasTrait(ptPublic)) then begin
|
|
|
Result := Result + string.Format('[%s]', [LPayloadContent]);
|
|
|
- end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.RecipientKeyEncrypted)) then begin
|
|
|
+ end else if (PayloadType.HasTrait(ptRecipientKeyEncrypted)) then begin
|
|
|
Result := Result + string.Format('(%s)', [LPayloadContent]);
|
|
|
- end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.SenderKeyEncrypted)) then begin
|
|
|
+ end else if (PayloadType.HasTrait(ptSenderKeyEncrypted)) then begin
|
|
|
Result := Result + string.Format('<%s>', [LPayloadContent]);
|
|
|
- end else if (PayloadTypes.IsPayloadTypeInSet(PayloadType.PasswordEncrypted)) then begin
|
|
|
+ end else if (PayloadType.HasTrait(ptPasswordEncrypted)) then begin
|
|
|
Result := Result + string.Format('{%s:%s}', [LPayloadContent, TPascalAsciiEncoding.Escape(Password)]);
|
|
|
end else begin
|
|
|
// it is non-deterministic, so payload omitted entirely
|
|
@@ -389,6 +434,11 @@ begin
|
|
|
end;
|
|
|
|
|
|
|
|
|
+class function TEPasa.GetEmptyValue : TEPasa;
|
|
|
+begin
|
|
|
+ Result := EmptyEPasa;
|
|
|
+end;
|
|
|
+
|
|
|
{ TEPasaParser }
|
|
|
|
|
|
class constructor TEPasaParser.CreateRegexEPasaParser;
|
|
@@ -465,8 +515,8 @@ begin
|
|
|
// when multiple enums are OR'ed in C#, they are combined and
|
|
|
// if any of the enums numeric value is zero, it is excluded.
|
|
|
// in our case,"PayloadType.NonDeterministic" is always zero so we exclude it from our set.
|
|
|
- AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.AddressedByName] -
|
|
|
- [PayloadType.NonDeterministic];
|
|
|
+ AEPasa.PayloadType := AEPasa.PayloadType + [ptAddressedByName] -
|
|
|
+ [ptNonDeterministic];
|
|
|
AEPasa.AccountName := TPascal64Encoding.Unescape(LAccountName);
|
|
|
AEPasa.Account := Nil;
|
|
|
AEPasa.AccountChecksum := Nil;
|
|
@@ -504,23 +554,23 @@ begin
|
|
|
AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
|
|
|
Exit(False);
|
|
|
end;
|
|
|
- AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.Public] -
|
|
|
- [PayloadType.NonDeterministic];
|
|
|
+ AEPasa.PayloadType := AEPasa.PayloadType + [ptPublic] -
|
|
|
+ [ptNonDeterministic];
|
|
|
end;
|
|
|
'(': begin
|
|
|
if (LPayloadEndChar <> ')') then begin
|
|
|
AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
|
|
|
Exit(False);
|
|
|
end;
|
|
|
- AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.RecipientKeyEncrypted] - [PayloadType.NonDeterministic];
|
|
|
+ AEPasa.PayloadType := AEPasa.PayloadType + [ptRecipientKeyEncrypted] - [ptNonDeterministic];
|
|
|
end;
|
|
|
'<': begin
|
|
|
if (LPayloadEndChar <> '>') then begin
|
|
|
AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
|
|
|
Exit(False);
|
|
|
end;
|
|
|
- AEPasa.PayloadTypes := AEPasa.PayloadTypes +
|
|
|
- [PayloadType.SenderKeyEncrypted] - [PayloadType.NonDeterministic];
|
|
|
+ AEPasa.PayloadType := AEPasa.PayloadType +
|
|
|
+ [ptSenderKeyEncrypted] - [ptNonDeterministic];
|
|
|
end;
|
|
|
|
|
|
'{': begin
|
|
@@ -528,13 +578,13 @@ begin
|
|
|
AErrorCode := EPasaErrorCode.MismatchedPayloadEncoding;
|
|
|
Exit(False);
|
|
|
end;
|
|
|
- AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.PasswordEncrypted] - [PayloadType.NonDeterministic];
|
|
|
+ AEPasa.PayloadType := AEPasa.PayloadType + [ptPasswordEncrypted] - [ptNonDeterministic];
|
|
|
end
|
|
|
else raise ENotSupportedException.CreateResFmt(@SUnRecognizedStartCharacter, [LPayloadStartChar]);
|
|
|
end;
|
|
|
|
|
|
// Password
|
|
|
- if (AEPasa.PayloadTypes.IsPayloadTypeInSet(PayloadType.PasswordEncrypted)) then begin
|
|
|
+ if (AEPasa.PayloadType.HasTrait(ptPasswordEncrypted)) then begin
|
|
|
if (LPayloadPasswordDelim = #0) then begin
|
|
|
AErrorCode := EPasaErrorCode.MissingPassword;
|
|
|
Exit(False);
|
|
@@ -551,25 +601,25 @@ begin
|
|
|
if (LPayloadContent = #0) then begin
|
|
|
AEPasa.Payload := string.Empty;
|
|
|
end else if (LPayloadContent.StartsWith('"')) then begin
|
|
|
- AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.AsciiFormatted] - [PayloadType.NonDeterministic];
|
|
|
+ AEPasa.PayloadType := AEPasa.PayloadType + [ptAsciiFormatted] - [ptNonDeterministic];
|
|
|
AEPasa.Payload := TPascalAsciiEncoding.UnEscape(LPayloadContent.Trim(['"']));
|
|
|
end else if (LPayloadContent.StartsWith('0x')) then begin
|
|
|
- AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.HexFormatted] - [PayloadType.NonDeterministic];
|
|
|
+ AEPasa.PayloadType := AEPasa.PayloadType + [ptHexFormatted] - [ptNonDeterministic];
|
|
|
AEPasa.Payload := System.Copy(LPayloadContent, 3, LPayloadContent.Length - 2);
|
|
|
end else begin
|
|
|
- AEPasa.PayloadTypes := AEPasa.PayloadTypes + [PayloadType.Base58Formatted] - [PayloadType.NonDeterministic];
|
|
|
+ AEPasa.PayloadType := AEPasa.PayloadType + [ptBase58Formatted] - [ptNonDeterministic];
|
|
|
AEPasa.Payload := LPayloadContent;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
// Payload Lengths
|
|
|
- if (not TEPasaHelper.IsValidPayloadLength(AEPasa.PayloadTypes, AEPasa.Payload)) then begin
|
|
|
+ if (not TEPasaComp.IsValidPayloadLength(AEPasa.PayloadType, AEPasa.Payload)) then begin
|
|
|
AErrorCode := EPasaErrorCode.PayloadTooLarge;
|
|
|
Exit(False);
|
|
|
end;
|
|
|
|
|
|
// Extended Checksum
|
|
|
- LActualChecksum := TEPasaHelper.ComputeExtendedChecksum(AEPasa.ToString(True));
|
|
|
+ LActualChecksum := TEPasaComp.ComputeExtendedChecksum(AEPasa.ToString(True));
|
|
|
if (LExtendedChecksumDelim <> #0) then begin
|
|
|
if (LExtendedChecksum <> LActualChecksum) then begin
|
|
|
AErrorCode := EPasaErrorCode.BadExtendedChecksum;
|
|
@@ -582,16 +632,16 @@ begin
|
|
|
end;
|
|
|
|
|
|
|
|
|
-{ TEPasaHelper }
|
|
|
+{ TEPasaComp }
|
|
|
|
|
|
-class function TEPasaHelper.ReadUInt16AsBytesLE(AValue: UInt16): TArray<Byte>;
|
|
|
+class function TEPasaComp.ReadUInt16AsBytesLE(AValue: UInt16): TArray<Byte>;
|
|
|
begin
|
|
|
System.SetLength(Result, System.SizeOf(UInt16));
|
|
|
Result[0] := Byte(AValue);
|
|
|
Result[1] := Byte(AValue shr 8);
|
|
|
end;
|
|
|
|
|
|
-class function TEPasaHelper.ComputeExtendedChecksum(const AText: String): String;
|
|
|
+class function TEPasaComp.ComputeExtendedChecksum(const AText: String): String;
|
|
|
var
|
|
|
LHashInstance: IHashWithKey;
|
|
|
LChecksum: UInt16;
|
|
@@ -602,53 +652,53 @@ begin
|
|
|
Result := THexEncoding.Encode(ReadUInt16AsBytesLE(LChecksum), True);
|
|
|
end;
|
|
|
|
|
|
-class function TEPasaHelper.IsValidExtendedChecksum(const AText, AChecksum: String): Boolean;
|
|
|
+class function TEPasaComp.IsValidExtendedChecksum(const AText, AChecksum: String): Boolean;
|
|
|
begin
|
|
|
Result := ComputeExtendedChecksum(AText) = AChecksum;
|
|
|
end;
|
|
|
|
|
|
-class function TEPasaHelper.IsValidPayloadLength(APayloadType: PayloadTypes; const APayloadContent: String): Boolean;
|
|
|
+class function TEPasaComp.IsValidPayloadLength(APayloadType: TPayloadType; const APayloadContent: String): Boolean;
|
|
|
begin
|
|
|
if (string.IsNullOrEmpty(APayloadContent)) then
|
|
|
Exit(True);
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.Public)) then begin
|
|
|
+ if (APayloadType.HasTrait(ptPublic)) then begin
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptAsciiFormatted)) then
|
|
|
Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxPublicAsciiContentLength);
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.HexFormatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptHexFormatted)) then
|
|
|
Exit(APayloadContent.Length <= MaxPublicHexContentLength);
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptBase58Formatted)) then
|
|
|
Exit(APayloadContent.Length <= MaxPublicBase58ContentLength);
|
|
|
|
|
|
// unknown encoding format
|
|
|
Result := False;
|
|
|
end;
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.SenderKeyEncrypted) or APayloadType.IsPayloadTypeInSet(PayloadType.RecipientKeyEncrypted)) then begin
|
|
|
+ if (APayloadType.HasTrait(ptSenderKeyEncrypted) or APayloadType.HasTrait(ptRecipientKeyEncrypted)) then begin
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptAsciiFormatted)) then
|
|
|
Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxECIESAsciiContentLength);
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.HexFormatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptHexFormatted)) then
|
|
|
Exit(APayloadContent.Length <= MaxECIESHexContentLength);
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptBase58Formatted)) then
|
|
|
Exit(APayloadContent.Length <= MaxECIESBase58ContentLength);
|
|
|
// unknown encoding format
|
|
|
Result := False;
|
|
|
end;
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.PasswordEncrypted)) then begin
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.AsciiFormatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptPasswordEncrypted)) then begin
|
|
|
+ if (APayloadType.HasTrait(ptAsciiFormatted)) then
|
|
|
Exit(TPascalAsciiEncoding.UnEscape(APayloadContent).Length <= MaxAESAsciiContentLength);
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.HexFormatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptHexFormatted)) then
|
|
|
Exit(APayloadContent.Length <= MaxAESHexContentLength);
|
|
|
|
|
|
- if (APayloadType.IsPayloadTypeInSet(PayloadType.Base58Formatted)) then
|
|
|
+ if (APayloadType.HasTrait(ptBase58Formatted)) then
|
|
|
Exit(APayloadContent.Length <= MaxAESBase58ContentLength);
|
|
|
|
|
|
// unknown encoding format
|
|
@@ -659,10 +709,41 @@ begin
|
|
|
Result := False;
|
|
|
end;
|
|
|
|
|
|
-class function TEPasaHelper.IsValidPasswordLength(const APasswordValue : String): Boolean;
|
|
|
+class function TEPasaComp.IsValidPasswordLength(const APasswordValue : String): Boolean;
|
|
|
begin
|
|
|
// no password length policy established (only client-side concern)
|
|
|
Result := True;
|
|
|
end;
|
|
|
|
|
|
+class function TEPasaComp.GetPayloadTypeProtocolByte(const APayloadType : TPayloadType) : Byte;
|
|
|
+var
|
|
|
+ LPayloadType : TPayloadTrait;
|
|
|
+begin
|
|
|
+ Result := 0; // NonDeterministic by default
|
|
|
+ for LPayloadType := Low(TPayloadTrait) to High(TPayloadTrait) do
|
|
|
+ if APayloadType.HasTrait(LPayloadType) then
|
|
|
+ Result := Result OR LPayloadType.ProtocolValue;
|
|
|
+end;
|
|
|
+
|
|
|
+class function TEPasaComp.GetPayloadTypeFromProtocolByte(AByte: Byte) : TPayloadType;
|
|
|
+var
|
|
|
+ LPayloadType : TPayloadTrait;
|
|
|
+ LPayloadTypeByte : byte;
|
|
|
+begin
|
|
|
+ if AByte = 0 then
|
|
|
+ Exit([ptNonDeterministic]);
|
|
|
+
|
|
|
+ Result := [];
|
|
|
+ for LPayloadType := Low(TPayloadTrait) to High(TPayloadTrait) do begin
|
|
|
+ LPayloadTypeByte := LPayloadType.ProtocolValue;
|
|
|
+ if (AByte AND LPayloadTypeByte) = LPayloadTypeByte then
|
|
|
+ Result := Result + [LPayloadType];
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+initialization
|
|
|
+
|
|
|
+EmptyEPasa := Default(TEPasa);
|
|
|
+
|
|
|
+
|
|
|
end.
|