Skip to content

Fix hashIdentifier normalization bug #22

Description

@Just-Bamford

Summary

The hashIdentifier function has a normalization bug. Input identifiers with different whitespace, case, or encoding produce different hashes, breaking the guarantee that the same identifier always hashes to the same value. This causes token validation failures when a voter's identifier is entered inconsistently.

This is a Milestone 1 bug. Token validation relies on consistent hashing.

Background

In js/src/crypto/hash.ts, the hashIdentifier function does not normalize the input before hashing. It currently does:

const hash = crypto.createHash('sha256').update(identifier).digest('hex');

If a voter enters their identifier with different whitespace (leading/trailing spaces), different case (uppercase vs lowercase), or different Unicode normalization (NFD vs NFC), the hash will be different and token validation will fail.

Scope

Crypto Library

  • Add normalization to hashIdentifier:
    • Trim leading and trailing whitespace
    • Convert to lowercase
    • Normalize Unicode to NFC
    • Remove any non-alphanumeric characters except hyphens and underscores
  • Document the normalization steps in comments and JSDoc
  • Update tests to verify normalized and non-normalized inputs hash to the same value

Tests

  • Leading/trailing spaces are trimmed
  • Uppercase converted to lowercase
  • Different Unicode representations hash to the same value
  • Non-alphanumeric characters removed
  • Example: " John Doe " and "john doe" hash to the same value

Relevant Files

  • js/src/crypto/hash.ts
  • js/src/tests/crypto.test.ts

Acceptance Criteria

  • All normalization steps implemented
  • Tests pass
  • No breaking changes to existing hashes (verify with backend)

Out of Scope

  • Custom normalization rules per ballot — use standard normalization only

Note for Contributors

Be careful with Unicode normalization. Use String.prototype.normalize('NFC') in Node.js. Test with international characters and emoji to ensure robustness. Do not change the hash format — keep it as hex string.

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26bugSomething isn't workingcryptoLabel: crypto

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions