tom_crypto 1.4.0
tom_crypto: ^1.4.0 copied to clipboard
Cryptographic utilities for secure authentication and data protection including JWT tokens, password hashing, and RSA encryption.
1.4.0 #
- Added:
TomProtectedValue— a secret held in memory, XOR-ed with a per-instance salt drawn fromTomSecureBytes, read only throughreveal(), identified by a SHA-256digestthat equality compares, shown asTomProtectedValue.maskbytoString(), and refused byjsonEncode. It came from the Webwork app, where it wasWebworkProtectedValue. A second entry point,package:tom_crypto/protected_value.dart, holds it alone and needs onlytom_basics; the barrel exports it too. - Dependencies:
dart_jsonwebtoken^3.4.1 andpointycastle^4.0.0, so the package resolves beside the other shared packages that use pointycastle 4;tom_basicsby path, andpublish_to: none, until the extracted packages are published together.
1.3.0 #
- Added:
TomJwtConfiguration.keyId. When set, every token signed with the configuration carries it as thekidheader, so a verifier holding several keys — one being retired beside its successor — picks the right one, and a JSON Web Key Set can publish each key under the same id. - Added:
TomServerJwtToken.audience. When given, the token carries it as theaudclaim, so a verifier can refuse a token minted for another service. test/jwt_key_id_audience_test.dartcovers both, and an RS256 token verified against the public key.
1.2.2 #
- Changed:
TomClientJwtToken.payloadis read-only. It returned the live decoded map, so a reader of a token could edit a claim with one statement and the token afterwards could not tell what it decoded from what somebody assigned. It now returns an unmodifiable view; assigning, inserting, removing or clearing throwsUnsupportedError, and a refused edit leaves the next read unchanged.test/jwt_payload_readonly_test.dartpins each case. - Fixed:
validUntilandexpare the same instant, in UTC. A token carried both, written from two clock reads in two encodings:expin epoch seconds andvalidUntilas an offset-less local ISO string, which means whatever the reader's zone says it means. A token minted in one zone and read in another was out by the difference. Issue now takes one clock read, in UTC, truncated to whole seconds;validUntil/validFromend inZ, andexp/nbfare written into the payload from that same instant instead of being recomputed bysign.test/jwt_validity_window_test.dartassertsexp == validUntilandnbf == validFromto the second. - Changed: requires
tom_basics3.0.0 or later. - Removed: the unused
lib/src/version.versioner.dartstamp. Nothing exported or read it.
1.2.1 #
- Fixed: a token's validity window was never quite the width it was asked
for.
TomServerJwtTokenwrotevalidUntilandvalidFromas offsets fromDateTime.now(), calling it once for each, so the two claims were offsets from two instants a few microseconds apart. The window came out marginally narrower thanexpiresIn - notBefore, and with the default zeronotBeforethevalidFromclaim named an instant slightly after the issue it stands for. Both are now offsets from a single clock read. The skew was sub-millisecond and never wrongly expired a token, but it made the two claims impossible to reason about as a pair —validUntil.difference(validFrom)did not equal the duration the caller passed. - Added:
test/jwt_validity_window_test.dart, which asserts that equality directly, including for a one-millisecond window where the old skew could exceed the window itself.
1.2.0 #
- Fixed:
TomJwtConfigurationcould not be constructed by a consumer. All four positional parameters of its constructor are typed by this package's dependencies —JWTKeyandJWTAlgorithmfromdart_jsonwebtoken,RSAPrivateKeyandRSAPublicKeyfrompointycastle— and none of the four was exported, so no code outside this package could name them. The class's own dartdoc documents the construction it made impossible.TomClientJwtToken.tokenand.audiencehad the same problem: their values could be read but their types could not be written down. - Added: the barrel now exports the types this package's public API names —
Audience,JWT,JWTAlgorithm,JWTKeyandSecretKeyfromdart_jsonwebtoken, andRSAPrivateKeyandRSAPublicKeyfrompointycastle. The lists are exactly the names this surface mentions. Both dependencies declare anRSAPrivateKeyand anRSAPublicKey, so exporting either wholesale would give consumers an ambiguous name; the pointycastle pair wins because it is whatTomJwtConfigurationholds and whatRsaKeyHelper.parsePrivateKeyFromPemreturns. Code needingdart_jsonwebtoken's own RSA/EC/EdDSA signing keys, which this surface never names, imports that package directly. - Added:
test/barrel_surface_test.dart, a compile-time guard. It imports only the barrel and names each type in a declaration, so losing an export stops the file compiling rather than failing an assertion inside it.
1.1.0 #
- Fixed: secure random bytes could never take the value
255. Both places that drew raw randomness usedRandom.nextInt(255), whose bound is exclusive, so every generated byte fell in0..254. This affected the Fortuna seed inRsaKeyHelper.getSecureRandom(and therefore every RSA key pair) and the salt inTomPasswordHasher.generateSalt(which is hex-encoded into the storedsalt$hash). The loss is about 0.0056 bits per byte. Existing password hashes remain verifiable — the salt is stored alongside the hash — so no migration is required. - Added:
TomSecureBytes.generate, now the single source of raw randomness in this package. Both call sites above previously carried their own copy of the same draw loop, and both copies were wrong in the same way; there is now one implementation for a third copy to not drift from.
1.0.0 #
- Initial version.