Skip to content

proposal: encoding/{base32,base64}: constant-time implementations of RFC 4648 codecs for use with cryptography keys #73901

Open
@tob-scott-a

Description

@tob-scott-a

Proposal Details

Background

The current implementations of the base32 and base64 codecs are not ideal for cryptographic use cases. The linked document describes practical timing side-channels against general purpose RFC 4648 codecs when used to encode/decode cryptographic secrets. You can verify the current implementation uses a table look-up in both directions, which introduces the risk of cache-timing attacks.

Specialized implementations of these codecs exist. @Sc00bz wrote a constant-time implementation of base64 in C, which I used as a basis for both base32 and base64 in PHP.

Proposed Change

New functions in encoding/base32 and encoding/base64:

  • EncodeToStringConstTime as an alternative to EncodeToString
  • DecodeStringConstTime as an alternative to DecodeString

These functions could then be used in other packages that handle cryptographic secrets and auditors can be absolutely sure that timing leaks are not present.

(I'm happy to provide a patch for this, if accepted.)

Activity

added this to the Proposal milestone on May 28, 2025
mateusz834

mateusz834 commented on May 28, 2025

@mateusz834
Member

CC @golang/security

added
Proposal-CryptoProposal related to crypto packages or other security issues
on May 28, 2025
tob-scott-a

tob-scott-a commented on May 28, 2025

@tob-scott-a
Author

Just in case there's any confusion: I do not think this qualifies as a security vulnerability (or I would have reported it as one, rather than filing an issue with the intent to follow up with a patch).

added
LibraryProposalIssues describing a requested change to the Go standard library or x/ libraries, but not to a tool
on May 28, 2025
Jorropo

Jorropo commented on May 28, 2025

@Jorropo
Member

👍 however do we want new functions ? It would be simpler for everyone if we made the current functions constant time.
If you could send your patch already it would be nice, I would like to benchmark it.

tob-scott-a

tob-scott-a commented on May 28, 2025

@tob-scott-a
Author

A constant-time alternative will certainly be slower than the general-purpose functions: It replaces a map look-up with many operations.

In the context of handling cryptographic secrets, this trade-off is worth it. However, making all use-cases for a base64 codec constant-time would slow most Go programs down unnecessarily.

It is for this reason that my opening offer was to implement new functions rather than change the current behavior.

Jorropo

Jorropo commented on May 28, 2025

@Jorropo
Member

A single map lookup is far from cheap, I don't want to risk myself to guessing the performance impact, a benchmark would really help 🙂.
Also in go we often do not mind trading a few % of performance if it means making the API easier to use.

mateusz834

mateusz834 commented on May 28, 2025

@mateusz834
Member

Also in go we often do not mind trading a few % of performance if it means making the API easier to use.

We can always do this in reverse, make the current API constant-time, but add unsafe variants (if needed) for speed. Then folks would actually use the constant-time APIs, otherwise we might have low usage of such (new) APIs.

renthraysk

renthraysk commented on May 28, 2025

@renthraysk

Doesn't the fact that stdlib have configurable alphabets for the base64/32 rule out replacing them?

tob-scott-a

tob-scott-a commented on May 29, 2025

@tob-scott-a
Author

@renthraysk It's not actually a total show-stopper (although it does make the patch a bit trickier to write). See #73909 for a first pass at a patch that adheres to the suggestions provided in this discussion so far.

gopherbot

gopherbot commented on May 29, 2025

@gopherbot
Contributor

Change https://go.dev/cl/676917 mentions this issue: encoding/base64: add constant-time behavior, enabled by default

rolandshoemaker

rolandshoemaker commented on May 29, 2025

@rolandshoemaker
Member

I don't think we'd want to turn on constant-time behavior by default for all uses of encoding/{base32,base64}. I suspect the vast majority of their usage is for entirely benign inputs. That said we probably would want to use it by default for encoding/pem, where the contents are much more likely to be sensitive (of course we should probably still add some way to disable this, for people who i.e. need to parse large numbers of certificates etc).

I haven't thought through this too deeply, but based on my understanding of how people typically do constant time base64, could we add a generic decoder/encoder that generates the required bit shift offsets based on the alphabet, rather than needing to implement per-alphabet encoders and decoders? We'd then just need to add a WithConstantTime (or something) method to Encoder.

17 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    LibraryProposalIssues describing a requested change to the Go standard library or x/ libraries, but not to a toolProposalProposal-CryptoProposal related to crypto packages or other security issues

    Type

    No type

    Projects

    Status

    Active

    Relationships

    None yet

      Development

      Participants

      @neild@Sc00bz@aclements@rolandshoemaker@gopherbot

      Issue actions

        proposal: encoding/{base32,base64}: constant-time implementations of RFC 4648 codecs for use with cryptography keys · Issue #73901 · golang/go