diff --git a/lib/src/cryptographic.dart b/lib/src/cryptographic.dart index 9a4ed39..0017bd4 100644 --- a/lib/src/cryptographic.dart +++ b/lib/src/cryptographic.dart @@ -77,4 +77,18 @@ class Cryptographic { } return result.toString(); } + + /// Returns a random URL-safe Base64-encoded string (padded). + /// + /// [entropy] is optional number of bytes (default is 32). + /// + /// Example: + /// ```dart + /// Cryptographic().tokenUrlSafe(); // "ti3YgkBb5xftxifepAgtKSWNM6uDEgr0R_OZV6XpfRs=" + /// Cryptographic().tokenUrlSafe(entropy: 64); // "HgudGr6yXgulDTK23x49-WPv3PqB7mn-D7n4fgNWMDGGCaffLD_0eXj4KpnAfPWImV5FzZiGFL4t3irb8FH29A==" + /// ``` + String tokenUrlSafe({int entropy = 32}) { + final bytes = tokenBytes(entropy: entropy); + return base64UrlEncode(bytes); + } } diff --git a/test/src/cryptographic_test.dart b/test/src/cryptographic_test.dart index 8ac7d1e..f778084 100644 --- a/test/src/cryptographic_test.dart +++ b/test/src/cryptographic_test.dart @@ -63,5 +63,20 @@ void main() { ); } }); + + test('returns url-safe base64 padded string', () { + final result = crypto.tokenUrlSafe(); + expect(result.length, greaterThan(32)); + expect(seededCrypto.tokenUrlSafe(), equals(seededCrypto.tokenUrlSafe())); + + for (final entropy in [64, 128]) { + final result = crypto.tokenUrlSafe(entropy: entropy); + expect(result.length, greaterThan(entropy)); + expect( + seededCrypto.tokenUrlSafe(entropy: entropy), + equals(seededCrypto.tokenUrlSafe(entropy: entropy)), + ); + } + }); }); }