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

crypto/cipher: GCM AEAD can be created with a custom nonce OR tag size, but not both #42470

Open
rustyx opened this issue Nov 9, 2020 · 11 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@rustyx
Copy link

rustyx commented Nov 9, 2020

What version of Go are you using (go version)?

$ go version
go version go1.15 windows/amd64

Does this issue reproduce with the latest release?

Yes, any version, any OS, any CPU.

What did you do?

I need to do AES GCM with both a custom nonce and a custom tag size - 16 and 12 bytes, respectively (the standard is 12 and 16).

The crypto API offers only NewGCMWithNonceSize and NewGCMWithTagSize public API's for creating a cipher with either a custom nonce or a custom tag size, but not both.

I see no technical reason for this limitation given there is a private API that does just that - newGCMWithNonceAndTagSize.

I had no problems doing this in Java and PHP and it's not feasible to change our production encryption because of the Go public API limitation.

What did you expect to see?

I expect the Go public API to allow AES GCM encryption with custom nonce and tag sizes.

What did you see instead?

Instead I'm forced to hack Go and invoke a private API like this

//go:linkname newGCMWithNonceAndTagSize crypto/cipher.newGCMWithNonceAndTagSize
func newGCMWithNonceAndTagSize(cipher cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error)

func Encrypt(s string, key []byte) (string, error) {
    c, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }
    gcm, err := newGCMWithNonceAndTagSize(c, 16, 12)
    . . .

Works like a charm, but I'd rather use public API's instead.

@tmthrgd
Copy link
Contributor

tmthrgd commented Nov 10, 2020

This was previously discussed in #34594 and declined because no one came forward with any protocol that required both.

@rustyx
Copy link
Author

rustyx commented Nov 10, 2020

AES GCM is not only for use in a protocol, it's a message encryption standard, see Dworkin, M., "Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC", National Institute of Standards and Technology SP 800-38D, November 2007"

We use it to encrypt messages in our application. Since the messages are short, we shorten the tag from the recommended 16 down to 12 bytes, which provides sufficient security in our case. And we use the GCM built-in nonce strengthening mechanism by supplying a 16-byte plaintext nonce and letting the cipher derive the necessary 12-byte nonce for use in the IV. The derivation is non-trivial and not easily reproduceable before invoking NewGCMWithTagSize.

In other words we could say we have a protocol, but it's not public.

Thus hereby a request to rename newGCMWithNonceAndTagSize to NewGCMWithNonceAndTagSize.

@cagedmantis cagedmantis changed the title crypto GCM AEAD can be created with a custom nonce OR tag size, but not both crypto/cipher: GCM AEAD can be created with a custom nonce OR tag size, but not both Nov 10, 2020
@cagedmantis cagedmantis added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Nov 13, 2020
@cagedmantis cagedmantis added this to the Backlog milestone Nov 13, 2020
@cagedmantis
Copy link
Contributor

/cc @FiloSottile

@darnfish
Copy link

darnfish commented Feb 9, 2021

+1 this

@Rusted2361
Copy link

+1
I have a custom encryption done with custom tage and nonce in nodejs this should be part of go private Api

@misberner
Copy link

Another aspect is cross-language capability. javax.crypto requires both nonce size and tag length to be specified in GCMParameterSpec.

I don't want to deviate from either the 12 byte nonce or the 16 byte tag, but it would be nice to have constants in both languages that fully describe the behavior for guaranteed interoperability.

@ghost
Copy link

ghost commented Feb 21, 2024

I would also like to support this issue. In cryptography, default parameters tend to change as new research emerges and supporting compatibility requires to make these configurable. Only being able to configure one or the other, but not both doesn't lend itself to creating an easy configuration.

@gearnode
Copy link

gearnode commented Apr 5, 2024

As a maintainer of a Go client for PrivateBin, I've encountered a significant limitation due to the protocol's support for custom nonce sizes and tag sizes. The current state of the public interface hinders the proper implementation of secret decryption according to the PrivateBin protocol standards. Reinstating the newGCMWithNonceAndTagSize function as a public entity would immensely facilitate compliance with these protocol specifications.

@FiloSottile
Copy link
Contributor

@gearnode could you point me to the relevant part of the PrivateBin protocol?

@gearnode
Copy link

gearnode commented Apr 5, 2024

@FiloSottile

In the PrivateBin protocol, the tag size variable can differ across implementations. Despite this variability, the tag size is consistently specified within the spec object for each implementation[1]. This ensures that clients can dynamically adapt by referencing the spec object to determine the correct tag size for encryption or decryption. The nonce value, crucial for encryption security, is also included in the spec object and is set to 16[2].

Currently, my implementation requires setting a custom nonce size to 16. Additionally, the variable tag size, which is not consistently set to 16 across all implementations, necessitates an hack to accommodate these variations. This requirement to adjust both the nonce and tag sizes, due to the flexibility allowed by the PrivateBin protocol, leads to the need for custom workarounds in the Go environment to ensure compatibility and maintain encryption integrity.

[1] https://github.com/PrivateBin/PrivateBin/wiki/Encryption-format
[2] https://github.com/PrivateBin/PrivateBin/blob/master/js/privatebin.js#L1230
[3] https://github.com/PrivateBin/PrivateBin/blob/master/js/types.jsonld#L95

@FiloSottile
Copy link
Contributor

Do you know why PrivateBin supports customizable tag sizes, and/or why it uses 128-bit nonces (which are treated differently from 96-bit nonces in GCM, so don't necessarily provide better security)?

I ask these questions because the goal of Go is not to be universally compatible with every possible configuration, but with useful and/or popular configurations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

8 participants