{
  "$comment": "GENERATED by TimeBasedOneTimePasswords/tools/generate-test-vectors.py (OpenChargingTechnology/Whitepapers) - do not edit by hand. Regenerate by rerunning the generator.",
  "specification": "Open Charging Technology TOTP Token Format 1.0",
  "description": "Canonical TOTP generation vectors. Absent optional input parameters mean: pass null/undefined, so that the implementation's own defaulting is exercised. Vectors with a 'requires' list only apply to implementations providing all listed capabilities.",
  "vectors": [
    {
      "id": "defaults-slot-boundary",
      "description": "All defaults, timestamp exactly on a 30s slot boundary: remaining time is the full validity time.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1718611200000,
        "validityTimeSeconds": 30,
        "totpLength": 12
      },
      "expected": {
        "previous": "QT1cCdKsIb9e",
        "current": "akF3c7qY2uiu",
        "next": "1U70OgaBA48M",
        "remainingTimeSeconds": 30
      }
    },
    {
      "id": "defaults-mid-slot",
      "description": "All parameters defaulted (validity 30s, length 12, Base62 alphabet, HMAC-SHA256), mid-slot timestamp.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000
      },
      "expected": {
        "previous": "MdPU0jCm5tXz",
        "current": "CN63y502maVh",
        "next": "dI54vnA25m2h",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "length-23",
      "description": "Explicit token length of 23 characters.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "totpLength": 23
      },
      "expected": {
        "previous": "MdPU0jCm5tXzkaPrPj61KwI",
        "current": "CN63y502maVhAsv27Sd7JlE",
        "next": "dI54vnA25m2hWW3bUcdY13q",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "alphabet-decimal",
      "description": "Decimal alphabet (10 characters, modulo bias: 256 = 25*10 + 6).",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "alphabet": "0123456789"
      },
      "expected": {
        "previous": "233045043555",
        "current": "894361286613",
        "next": "545817627227",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "validity-60",
      "description": "60 second validity time.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "validityTimeSeconds": 60
      },
      "expected": {
        "previous": "nTdkiuG6yUyg",
        "current": "XJZr0L1DGKn0",
        "next": "ft0ONZ62MdMj",
        "remainingTimeSeconds": 55
      }
    },
    {
      "id": "sha384-defaults",
      "description": "HMAC-SHA384 (48 hash bytes) with default parameters.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "hashAlgorithm": "sha384"
      },
      "expected": {
        "previous": "0SbZV69lSa4W",
        "current": "jAzmwLzuPuUb",
        "next": "mqtkOMRrX1aS",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "sha512-defaults",
      "description": "HMAC-SHA512 (64 hash bytes) with default parameters.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "hashAlgorithm": "sha512"
      },
      "expected": {
        "previous": "wjmTW4LVTdwv",
        "current": "yBhTTbXO2ILd",
        "next": "MHMqTXE1oVf9",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "epoch-previous-slot-wraps",
      "description": "Timestamp 0: within the first slot after the Unix epoch the previous slot number wraps to 2^64 - 1 (unchecked 64 bit arithmetic).",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 0,
        "validityTimeSeconds": 30,
        "totpLength": 12
      },
      "expected": {
        "previous": "SzcwtcR5qcY7",
        "current": "u5CoKdo5HUS1",
        "next": "tVGiyLys7Y1V",
        "remainingTimeSeconds": 30
      }
    },
    {
      "id": "length-64-sha256-ring-buffer",
      "description": "A 64 character HMAC-SHA256 token: the hash is read as a ring buffer, so the 32 character token repeats verbatim.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1718611200000,
        "validityTimeSeconds": 30,
        "totpLength": 64
      },
      "expected": {
        "previous": "QT1cCdKsIb9e1gSulDAx9PYnnkX3e9h0QT1cCdKsIb9e1gSulDAx9PYnnkX3e9h0",
        "current": "akF3c7qY2uiuO4rpyU0SC0W8VFE6nvxzakF3c7qY2uiuO4rpyU0SC0W8VFE6nvxz",
        "next": "1U70OgaBA48Mul8hQCdP4MZ0eskSGKY31U70OgaBA48Mul8hQCdP4MZ0eskSGKY3",
        "remainingTimeSeconds": 30
      }
    },
    {
      "id": "length-6-decimal",
      "description": "Six decimal digits - the classic RFC 6238 look, in this token format.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1718611200000,
        "validityTimeSeconds": 30,
        "totpLength": 6,
        "alphabet": "0123456789"
      },
      "expected": {
        "previous": "277289",
        "current": "441749",
        "next": "127406",
        "remainingTimeSeconds": 30
      }
    },
    {
      "id": "length-min-4",
      "description": "Minimum allowed token length.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "totpLength": 4
      },
      "expected": {
        "previous": "MdPU",
        "current": "CN63",
        "next": "dI54",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "length-max-255",
      "description": "Maximum allowed token length (with SHA-512; positions beyond 64 repeat the ring buffer).",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "totpLength": 255,
        "hashAlgorithm": "sha512"
      },
      "expected": {
        "previous": "wjmTW4LVTdwvAoRnsVaQEGQNO6jl04EkDfx8WQ1wEoEEK3h7owa2CGzQ5BT02iaSwjmTW4LVTdwvAoRnsVaQEGQNO6jl04EkDfx8WQ1wEoEEK3h7owa2CGzQ5BT02iaSwjmTW4LVTdwvAoRnsVaQEGQNO6jl04EkDfx8WQ1wEoEEK3h7owa2CGzQ5BT02iaSwjmTW4LVTdwvAoRnsVaQEGQNO6jl04EkDfx8WQ1wEoEEK3h7owa2CGzQ5BT02ia",
        "current": "yBhTTbXO2ILdhc7l4DAFp1TIdSA9ZR75LDV00jflwqx24rsdf6SqzmNpcic22HsNyBhTTbXO2ILdhc7l4DAFp1TIdSA9ZR75LDV00jflwqx24rsdf6SqzmNpcic22HsNyBhTTbXO2ILdhc7l4DAFp1TIdSA9ZR75LDV00jflwqx24rsdf6SqzmNpcic22HsNyBhTTbXO2ILdhc7l4DAFp1TIdSA9ZR75LDV00jflwqx24rsdf6SqzmNpcic22Hs",
        "next": "MHMqTXE1oVf9AxQ65U1rtJToI4GB2WhDcI65enGY3JM9zcahAZjCWH738spwiNIlMHMqTXE1oVf9AxQ65U1rtJToI4GB2WhDcI65enGY3JM9zcahAZjCWH738spwiNIlMHMqTXE1oVf9AxQ65U1rtJToI4GB2WhDcI65enGY3JM9zcahAZjCWH738spwiNIlMHMqTXE1oVf9AxQ65U1rtJToI4GB2WhDcI65enGY3JM9zcahAZjCWH738spwiNI",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "length-33-sha256",
      "description": "One character beyond the 32 byte SHA-256 hash: position 32 repeats position 0.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "totpLength": 33
      },
      "expected": {
        "previous": "MdPU0jCm5tXzkaPrPj61KwIMNKAF7gMtM",
        "current": "CN63y502maVhAsv27Sd7JlErFxtg9tAUC",
        "next": "dI54vnA25m2hWW3bUcdY13qmNkNzzB06d",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "length-48-sha384",
      "description": "Token length equal to the 48 byte SHA-384 hash length.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "totpLength": 48,
        "hashAlgorithm": "sha384"
      },
      "expected": {
        "previous": "0SbZV69lSa4W67Z5jI40i4Q5tWXNOlR9UhqLJQaHLwdlPznV",
        "current": "jAzmwLzuPuUbsAOcoYn131tbGtsgEB9G6msuK1BET8yQVLCB",
        "next": "mqtkOMRrX1aSaoOZ61evpWRCwRIuPmauVxww53l3CKrxuEZg",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "length-64-sha512",
      "description": "Token length equal to the 64 byte SHA-512 hash length: no repetition.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "totpLength": 64,
        "hashAlgorithm": "sha512"
      },
      "expected": {
        "previous": "wjmTW4LVTdwvAoRnsVaQEGQNO6jl04EkDfx8WQ1wEoEEK3h7owa2CGzQ5BT02iaS",
        "current": "yBhTTbXO2ILdhc7l4DAFp1TIdSA9ZR75LDV00jflwqx24rsdf6SqzmNpcic22HsN",
        "next": "MHMqTXE1oVf9AxQ65U1rtJToI4GB2WhDcI65enGY3JM9zcahAZjCWH738spwiNIl",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "alphabet-min-4",
      "description": "Minimum allowed alphabet size (4 characters).",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "alphabet": "ACGT"
      },
      "expected": {
        "previous": "ACCAACAACTCT",
        "current": "GCGTATGAGACT",
        "next": "TACATTAGTGGC",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "alphabet-hex",
      "description": "Hexadecimal alphabet (16 characters, no modulo bias: 16 divides 256).",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "alphabet": "0123456789abcdef"
      },
      "expected": {
        "previous": "cd14cd44d753",
        "current": "61e30fec245b",
        "next": "bc50f3423621",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "alphabet-base32",
      "description": "RFC 4648 Base32 alphabet (32 characters, no modulo bias).",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "alphabet": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
      },
      "expected": {
        "previous": "MNRU4NEU5XVD",
        "current": "GR6DA764SEVL",
        "next": "LMFA7TECDWCR",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "alphabet-base64url",
      "description": "Base64url alphabet (64 characters, no modulo bias: 256 = 4*64). RECOMMENDED when bias matters.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "alphabet": "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
      },
      "expected": {
        "previous": "IdNQYdAkZnRz",
        "current": "CN-3w_-Yi4Rb",
        "next": "bI50vjA23m2h",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "validity-1",
      "description": "One second validity time: the slot number equals the Unix time.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "validityTimeSeconds": 1
      },
      "expected": {
        "previous": "4tCOMnYC1jyO",
        "current": "QypcM5hxJ94T",
        "next": "NaZqaahbFnb0",
        "remainingTimeSeconds": 1
      }
    },
    {
      "id": "validity-5",
      "description": "Five second validity time.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "validityTimeSeconds": 5
      },
      "expected": {
        "previous": "LYhXalw0w2O5",
        "current": "3bp8qljbQ6Th",
        "next": "ZELD377HHJpx",
        "remainingTimeSeconds": 5
      }
    },
    {
      "id": "validity-7",
      "description": "Seven second validity time - not a divisor of 60, exercises slot arithmetic.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "validityTimeSeconds": 7
      },
      "expected": {
        "previous": "9tmY7YPiGS9k",
        "current": "RpYIMd0IlQCZ",
        "next": "ihflnOIQeXKG",
        "remainingTimeSeconds": 1
      }
    },
    {
      "id": "validity-86400",
      "description": "One day validity time.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "validityTimeSeconds": 86400
      },
      "expected": {
        "previous": "YRo0d3AAG9h3",
        "current": "FRmyHBzwle4I",
        "next": "qr4tp5AYFetR",
        "remainingTimeSeconds": 85015
      }
    },
    {
      "id": "remaining-1-second",
      "description": "Last second of a slot: remaining time is 1.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423779000
      },
      "expected": {
        "previous": "nl0iABVo6jRY",
        "current": "MdPU0jCm5tXz",
        "next": "CN63y502maVh",
        "remainingTimeSeconds": 1
      }
    },
    {
      "id": "milliseconds-floor",
      "description": "Milliseconds are floored to whole seconds: x999 ms yields the same tokens as x000 ms.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785999
      },
      "expected": {
        "previous": "MdPU0jCm5tXz",
        "current": "CN63y502maVh",
        "next": "dI54vnA25m2h",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "milliseconds-floor-slot-edge",
      "description": "999 ms before a slot change: still the old slot, remaining time 1 second.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423809999
      },
      "expected": {
        "previous": "MdPU0jCm5tXz",
        "current": "CN63y502maVh",
        "next": "dI54vnA25m2h",
        "remainingTimeSeconds": 1
      }
    },
    {
      "id": "timestamp-y2038",
      "description": "Unix time 2^31 - 1 (2038-01-19T03:14:07Z): no 32 bit rollover.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 2147483647000
      },
      "expected": {
        "previous": "jf6k3NFpulnR",
        "current": "cSNjvhC7U5UN",
        "next": "ozVde74ViFzJ",
        "remainingTimeSeconds": 23
      }
    },
    {
      "id": "timestamp-year-9999",
      "description": "9999-12-31T23:59:28Z, the far end of the calendar.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 253402300768000
      },
      "expected": {
        "previous": "nYAGviXNwhe0",
        "current": "9ko7CWj5OI4E",
        "next": "qt0uZS0w35J0",
        "remainingTimeSeconds": 2
      }
    },
    {
      "id": "secret-utf8",
      "description": "Non-ASCII shared secret: the secret is encoded as UTF-8 before keying the HMAC. No Unicode normalization is applied.",
      "input": {
        "sharedSecret": "s\u00e9c\u00fcr\u00e8!Ch\u00e4rg\u00eeng!",
        "unixTimestampMillis": 1716423785000
      },
      "expected": {
        "previous": "2z9YFjk3E4Cs",
        "current": "SLuwWQOYh3g0",
        "next": "gG7F7AI3znvY",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "secret-64-chars",
      "description": "A long, 64 character shared secret.",
      "input": {
        "sharedSecret": "0ZPatRVe1DTLBHRipD5cyOU9d1TCsdLLYhtLXGajUATuOwaVSVFPnbUAJyTFrPFI",
        "unixTimestampMillis": 1716423785000
      },
      "expected": {
        "previous": "zxI4teacfH85",
        "current": "9Sk0VMKOc9nx",
        "next": "WOdiJz2UlhES",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "secret-surrounding-whitespace",
      "description": "The shared secret is trimmed before use: surrounding whitespace yields the tokens of the trimmed secret.",
      "input": {
        "sharedSecret": "  secure!Charging!  ",
        "unixTimestampMillis": 1716423785000
      },
      "expected": {
        "previous": "MdPU0jCm5tXz",
        "current": "CN63y502maVh",
        "next": "dI54vnA25m2h",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "alphabet-surrounding-whitespace",
      "description": "The alphabet is trimmed before use: surrounding whitespace yields the tokens of the trimmed alphabet.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "alphabet": " 0123456789 "
      },
      "expected": {
        "previous": "233045043555",
        "current": "894361286613",
        "next": "545817627227",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "ocpp-v1-length-8",
      "description": "OCPP 2.1 C25 'TOTP algorithm, version 1' with the example token length 8 of WebPaymentsCtrlr.Length.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "validityTimeSeconds": 30,
        "totpLength": 8
      },
      "expected": {
        "previous": "MdPU0jCm",
        "current": "CN63y502",
        "next": "dI54vnA2",
        "remainingTimeSeconds": 25
      }
    },
    {
      "id": "ocpp-v1-min-profile",
      "description": "The weakest OCPP-legal corner: WebPaymentsCtrlr minimum Length 6 with maximum ValidityTime 3600s.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "validityTimeSeconds": 3600,
        "totpLength": 6
      },
      "expected": {
        "previous": "kDDM3V",
        "current": "Ik0dNs",
        "next": "7eNFbx",
        "remainingTimeSeconds": 2215
      }
    },
    {
      "id": "all-parameters-custom",
      "description": "Every parameter away from its default at once.",
      "input": {
        "sharedSecret": "Conformance!Secret#2026",
        "unixTimestampMillis": 1716423785000,
        "validityTimeSeconds": 120,
        "totpLength": 20,
        "alphabet": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
        "hashAlgorithm": "sha384"
      },
      "expected": {
        "previous": "OQD6GMTMUU6VV6ZLEDJO",
        "current": "SUIRNOHSFW6M36DHFD6A",
        "next": "LLHIHOAWNZE5CLGBR72A",
        "remainingTimeSeconds": 55
      }
    },
    {
      "id": "tls-binding-sha256",
      "description": "TLS v1.3 channel binding: a second HMAC, keyed with 32 bytes of TLS exporter material, over the first digest.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "tlsExporterMaterialHex": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
      },
      "expected": {
        "previous": "a603aFLdBS79",
        "current": "gAzxPfYtmRgd",
        "next": "cwveP1RTF3PN",
        "remainingTimeSeconds": 25
      },
      "requires": [
        "tlsChannelBinding"
      ]
    },
    {
      "id": "tls-binding-sha512",
      "description": "TLS v1.3 channel binding with HMAC-SHA512: both HMACs use the same hash algorithm.",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "hashAlgorithm": "sha512",
        "tlsExporterMaterialHex": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
      },
      "expected": {
        "previous": "0863qOfjmKw9",
        "current": "0a0M1AiS8UQ9",
        "next": "1kWUIDYa0GyP",
        "remainingTimeSeconds": 25
      },
      "requires": [
        "tlsChannelBinding"
      ]
    },
    {
      "id": "tls-binding-short-material",
      "description": "TLS channel binding with only 8 bytes of exporter material (HMAC accepts any key length).",
      "input": {
        "sharedSecret": "secure!Charging!",
        "unixTimestampMillis": 1716423785000,
        "tlsExporterMaterialHex": "0011223344556677"
      },
      "expected": {
        "previous": "FDKc6MxclPd3",
        "current": "0Pb2AmvxeS0O",
        "next": "Vn1QgfzMZ7B0",
        "remainingTimeSeconds": 25
      },
      "requires": [
        "tlsChannelBinding"
      ]
    }
  ]
}
