Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce version 0x81, including microsecond timestamps #13

Closed
wants to merge 13 commits into from

Conversation

dolph
Copy link

@dolph dolph commented Oct 12, 2015

This change introduces a second version of the specification (0x81), and asserts that timestamps in tokens versioned as 0x81 be evaluated as microseconds since the epoch. The timestamp is still a 64-bit unsigned integer, which I believe is still totally sufficient.

Given that the timestamp is already a 64-bit unsigned big-endian
integer, the spec will remain viable for over 500,000 years.

This allows us to more precisely compare token creation timestamps
against revocation event timestamps (which already have microsecond
precision). This helps us avoid a race condition wherein a token can be
created *after* a revocation event, but appear to be created *before*
it, thus matching the revocation event and being considered invalid.
After this change, the specification is still vulnerable to this race
condition, but the time window to reproduce it is narrowed to a single
microsecond, instead of a single second.

Closes fernet#12
the token. Currently there is only one version defined, with the
value 128 (0x80).
This field denotes which version of the format is being used by the token.
Currently there is only one version defined, with the value 128 (0x80).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit is adding a second version. Or are we just noting changes from the original document with Changed in version 0x81?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, I totally missed this as I was focused on the timestamp field. Will revise.

This is mostly intended to further explain the change in version 0x81.
This will ensure that Github will render the spec on the repository's
homepage (the repo is already called "spec", after all!).
I think I wrote this thinking there was only one difference between the
two versions, my grammar followed suit, but the statement should be more
generic to handle more than just two versions and more than just one
difference between the existing two versions.
TODOs are serving as placeholders for actual 0x81 tokens, which I've
neither created by hand nor written an implementation to produce, yet.
I accidentally put them in the TZ, whoops!
I rebuilt the valid 0x80 tokens in the acceptance tests manually using
the following function to convert them. This explicitly illustrates the
differences between 0x80 and 0x81.

import base64
import hashlib
import hmac
import struct

def upgrade_to_81(x80_token, secret):
    """Upgrade an 0x80 token to 0x81 given a new timestamp and secret."""
    # Decode the 0x80 version token.
    x80_bytes = base64.urlsafe_b64decode(x80_token)

    # Unpack the timestamp so we can manipulate it.
    seconds = struct.unpack('>Q', x80_bytes[1:9])

    # Convert seconds to microseconds, and add some microseconds.
    microseconds = int(seconds * 1e6) + 123456

    x81_bytes = '\x81'  # New version identifier.
    x81_bytes += struct.pack(">Q", microseconds)
    x81_bytes += x80_bytes[9:-32]
    x81_bytes += hmac.new(
        base64.b64decode(secret)[16:],
        x81_bytes,
        hashlib.sha256).digest()

    return base64.urlsafe_b64encode(x81_bytes)
@dolph
Copy link
Author

dolph commented Oct 15, 2015

Test cases with microsecond data are in generate.json, verify.json, and invalid.json. For example:

https://github.com/dolph/fernet-spec/blob/2688de4d318bda3fcfa2a4808418a06948c9039a/generate.json

I'm not sure what you mean by the "or do we wait ..." (this is already a pull request against fernet/spec).

And no, I haven't written any sort of real implementation yet.

@dolph
Copy link
Author

dolph commented Nov 29, 2017

Closing and abandoning this, as I'm no longer a stakeholder.

@dolph dolph closed this Nov 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants