YOUSEFUL / DELPHI / COMPONENTS

TAtlasBytes

Byte helpers: hexadecimal, URL-safe base64, UTF-8, joining, constant-time comparison and wiping.

Class Unit Atlas.Crypto · Inherits TObject · Product Atlas Crypto

Description

A set of class functions; never create an instance. Keys, digests and signatures in Atlas Crypto are TBytes, and these helpers turn them into text and back, compare them safely and erase them.

Use ConstantTimeEquals, never = on strings or CompareMem, to compare a secret value such as an HMAC tag or a password hash with a received one. Use Wipe on keys and passwords once you are done with them. Delphi dynamic arrays are reference counted: Wipe zeroes the memory that every reference to the same array shares, but not copies made with Copy or by concatenation.

Members

MemberKindWhat it does
ToHexmethodReturns lower-case hexadecimal, two digits per byte.
FromHexmethodParses hexadecimal digits in either case.
ToBase64UrlmethodReturns base64 in the URL-safe alphabet (- and _ instead of + and /), without = padding and without line breaks, however long the data.
FromBase64UrlmethodParses text made by ToBase64Url.
OfStringmethodReturns the UTF-8 encoding of Text, the form every text-taking function in Atlas Crypto uses.
ConcatmethodJoins the parts in order into a new array.
ConstantTimeEqualsmethodTrue when both arrays have the same length and content.
WipemethodOverwrites the content with zeros, then sets Data to an empty array.

Methods

ToHex method

class function ToHex(const Data: TBytes): string; static;

Returns lower-case hexadecimal, two digits per byte. An empty array gives an empty string.

pascal
HexText := TAtlasBytes.ToHex(TBytes.Create($00, $AB, $FF));  // 00abff

FromHex method

class function FromHex(const Text: string): TBytes; static;

Parses hexadecimal digits in either case. Raises EAtlasCryptoError for an odd number of digits or any other character, including a 0x prefix or spaces.

pascal
Data := TAtlasBytes.FromHex('00ABff');

ToBase64Url method

class function ToBase64Url(const Data: TBytes): string; static;

Returns base64 in the URL-safe alphabet (- and _ instead of + and /), without = padding and without line breaks, however long the data.

pascal
Text := TAtlasBytes.ToBase64Url(TAtlasRandom.Bytes(32));  // 43 characters

FromBase64Url method

class function FromBase64Url(const Text: string): TBytes; static;

Parses text made by ToBase64Url. Raises EAtlasCryptoError (The text is not URL-safe base64) for any character outside A-Z, a-z, 0-9, - and _ (so padding, white space and the standard + and / are refused), and for an impossible length.

pascal
Data := TAtlasBytes.FromBase64Url(Text);

OfString method

class function OfString(const Text: string): TBytes; static;

Returns the UTF-8 encoding of Text, the form every text-taking function in Atlas Crypto uses.

pascal
Data := TAtlasBytes.OfString('grüße');  // 7 bytes

Concat method

class function Concat(const Parts: array of TBytes): TBytes; static;

Joins the parts in order into a new array. Empty parts are skipped; no parts give an empty array.

pascal
Data := TAtlasBytes.Concat([TAtlasBytes.OfString('v1:'), Key]);

ConstantTimeEquals method

class function ConstantTimeEquals(const A, B: TBytes): Boolean; static;

True when both arrays have the same length and content. For equal lengths the time taken depends only on the length, never on where the first difference is, so a comparison cannot leak a secret byte by byte. Arrays of different lengths return False at once. Two empty arrays are equal.

pascal
Valid := TAtlasBytes.ConstantTimeEquals(Tag, TAtlasHash.Hmac(hkSHA256, Key, Data));

Wipe method

class procedure Wipe(var Data: TBytes); static;

Overwrites the content with zeros, then sets Data to an empty array. Safe to call on an empty array.

pascal
TAtlasBytes.Wipe(Key);

Examples

Encode, compare and wipe

Prints 00abff, AKv_ and TRUE, then 0 after the wipe.

pascal
uses System.SysUtils, Atlas.Crypto;

procedure ByteHelpers;
var
  Secret: TBytes;
begin
  Secret := TBytes.Create($00, $AB, $FF);
  WriteLn(TAtlasBytes.ToHex(Secret));
  WriteLn(TAtlasBytes.ToBase64Url(Secret));
  WriteLn(TAtlasBytes.ConstantTimeEquals(TAtlasBytes.FromBase64Url('AKv_'), TAtlasBytes.FromHex('00ABFF')));
  TAtlasBytes.Wipe(Secret);
  WriteLn(Length(Secret));
end;

TAtlasRandom · TAtlasHash · TAtlasSecretBox

Also in Atlas Crypto

TAtlasHashCalculator · TAtlasFileProtector