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

x/crypto/openpgp: generated then serialized Keys have incorrect bitLength #23460

Closed
sowbug opened this issue Jan 17, 2018 · 2 comments
Closed

Comments

@sowbug
Copy link

sowbug commented Jan 17, 2018

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

go version go1.6.2 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/miket/go"
GORACE=""
GOROOT="/usr/lib/go-1.6"
GOTOOLDIR="/usr/lib/go-1.6/pkg/tool/linux_amd64"
GO15VENDOREXPERIMENT="1"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

What did you do?

Create GnuPG ECDSA key using ecdsa.GenerateKey(). Wrap it in an Entity, add a subkey, self-sign everything with the PrimaryKey, then entity.Serialize(). Pipe the output into gpg -v and note that the signatures reference a key ID that doesn't match the primary key's key ID:

pub   nistp256 2018-01-01 [SCA]
      706D981A9145B74E69BC36CFABC8AC51CCB4C520
uid           name (comment) <email>
sig        0659C02E556D4CA4 2018-01-01   [User ID not found]
sub   nistp256 2018-01-01 []
sig        0659C02E556D4CA4 2018-01-01   [User ID not found]

Pipe the same output into gpg --list-packets --verbose and confirm that yes, something's not right:

# off=0 ctb=c6 tag=6 hlen=2 plen=82 new-ctb
:public key packet:
	version 4, algo 19, created 1514764800, expires 0
	pkey[0]: 082A8648CE3D030107 nistp256 (1.2.840.10045.3.1.7)
	pkey[1]: 0458AE3AD137C5C9352F98303544E72117DE0628F56C9A3DE9619ED8039731EE1E9AAF9BEBA6982D64AC2CD9EEEE7899567275541DC470CCBBEA7B4CC086408AFA
	keyid: ABC8AC51CCB4C520
# off=84 ctb=cd tag=13 hlen=2 plen=22 new-ctb
:user ID packet: "name (comment) <email>"
# off=108 ctb=c2 tag=2 hlen=2 plen=97 new-ctb
:signature packet: algo 19, keyid 0659C02E556D4CA4
	version 4, created 1514764800, md5len 0, sigclass 0x13
	digest algo 8, begin of digest 44 96
	hashed subpkt 2 len 4 (sig created 2018-01-01)
	hashed subpkt 16 len 8 (issuer key ID 0659C02E556D4CA4)
	hashed subpkt 27 len 1 (key flags: 03)
	data: B5D8FB94670858ACC6F51B695887430EDF0EF33D91B38876490BF38724692768
	data: 540AFB966DF221C578D5B41379861D34779D235A14857DE27AA6AB3058FEF5A6
# off=207 ctb=ce tag=14 hlen=2 plen=82 new-ctb
:public sub key packet:
	version 4, algo 19, created 1514764800, expires 0
	pkey[0]: 082A8648CE3D030107 nistp256 (1.2.840.10045.3.1.7)
	pkey[1]: 041454608AD186F2E789A4016A3BC47D71F60D36DE0DD887D2F29F1E36DDBB8187767A371211339F40E380AEC31A06CC8C09F0A8C6A6CF65BD0B0E787DB37C036D
	keyid: A9FAFA8DC27BAF9B
# off=291 ctb=c2 tag=2 hlen=2 plen=103 new-ctb
:signature packet: algo 19, keyid 0659C02E556D4CA4
	version 4, created 1514764800, md5len 0, sigclass 0x18
	digest algo 8, begin of digest 17 98
	hashed subpkt 2 len 4 (sig created 2018-01-01)
	hashed subpkt 16 len 8 (issuer key ID 0659C02E556D4CA4)
	hashed subpkt 27 len 1 (key flags: 0C)
	hashed subpkt 9 len 4 (key expires after 1y0d0h0m)
	data: 70621FF909F9EC50155EB7537F035AEF9D7915C1A29ECB3D656D01F2D7FAB365
	data: 79F9BA2C5AA059BD64E6C4115E8210B843B2056D8609F5086FE2605944EFDB89

This is a code snippet that produces the error: https://gist.github.com/sowbug/5c1a950ea21b169975375d470b52fbfb

What did you expect to see?

I eventually figured out that the bitlength of the public key for a P256 key should be declared as 515 bits (see RFC 6637 -- 256 + 256 + 3 = 515), but https://github.com/golang/crypto/blob/master/openpgp/packet/public_key.go#L247 calculates it as round8(256 + 256 + 3) = 520. Since the stated bitlength is part of the OpenPGP fingerprint calculation, this throws off the key ID.

What did you see instead?

bit length should have been 515, but it was 520.

@gopherbot
Copy link

Change https://golang.org/cl/87995 mentions this issue: openpgp: serialize correct bitlength for generated ECC keys

@odeke-em odeke-em changed the title Keys generated and serialized in x/crypto/openpgp have incorrect bitlength x/crypto/openpgp: generated then serialized Keys have incorrect bitLength Jan 17, 2018
@gopherbot gopherbot added this to the Unreleased milestone Jan 17, 2018
@odeke-em
Copy link
Member

/cc @agl @aead

@golang golang locked and limited conversation to collaborators Mar 15, 2019
chintanparikh pushed a commit to opendoor-labs/openpgp that referenced this issue Dec 11, 2019
Rather than rounding the `type || X || Y` byte sequence to the next
8-bit boundary, packet.NewECDSAPublicKey() now rounds the X and Y
coordinates individually, then adds the bitlength 3 of type 4
(compressed). For NIST P-256, this leads to a bit length of 515,
rather than 520. GnuPG calculates 515 as well, and
https://tools.ietf.org/html/rfc6637#section-6 explicitly states that
"the exact size of the MPI payload is 515 bits for 'Curve P-256,'"
so the new formula is consistent.

Fixes golang/go#23460

Change-Id: I64b340d1c761bfd795a1a64dc2f7a831c8b2ff32
Reviewed-on: https://go-review.googlesource.com/87995
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
c-expert-zigbee pushed a commit to c-expert-zigbee/crypto_go that referenced this issue Mar 28, 2022
Rather than rounding the `type || X || Y` byte sequence to the next
8-bit boundary, packet.NewECDSAPublicKey() now rounds the X and Y
coordinates individually, then adds the bitlength 3 of type 4
(compressed). For NIST P-256, this leads to a bit length of 515,
rather than 520. GnuPG calculates 515 as well, and
https://tools.ietf.org/html/rfc6637#section-6 explicitly states that
"the exact size of the MPI payload is 515 bits for 'Curve P-256,'"
so the new formula is consistent.

Fixes golang/go#23460

Change-Id: I64b340d1c761bfd795a1a64dc2f7a831c8b2ff32
Reviewed-on: https://go-review.googlesource.com/87995
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
c-expert-zigbee pushed a commit to c-expert-zigbee/crypto_go that referenced this issue Mar 29, 2022
Rather than rounding the `type || X || Y` byte sequence to the next
8-bit boundary, packet.NewECDSAPublicKey() now rounds the X and Y
coordinates individually, then adds the bitlength 3 of type 4
(compressed). For NIST P-256, this leads to a bit length of 515,
rather than 520. GnuPG calculates 515 as well, and
https://tools.ietf.org/html/rfc6637#section-6 explicitly states that
"the exact size of the MPI payload is 515 bits for 'Curve P-256,'"
so the new formula is consistent.

Fixes golang/go#23460

Change-Id: I64b340d1c761bfd795a1a64dc2f7a831c8b2ff32
Reviewed-on: https://go-review.googlesource.com/87995
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
c-expert-zigbee pushed a commit to c-expert-zigbee/crypto_go that referenced this issue Mar 29, 2022
Rather than rounding the `type || X || Y` byte sequence to the next
8-bit boundary, packet.NewECDSAPublicKey() now rounds the X and Y
coordinates individually, then adds the bitlength 3 of type 4
(compressed). For NIST P-256, this leads to a bit length of 515,
rather than 520. GnuPG calculates 515 as well, and
https://tools.ietf.org/html/rfc6637#section-6 explicitly states that
"the exact size of the MPI payload is 515 bits for 'Curve P-256,'"
so the new formula is consistent.

Fixes golang/go#23460

Change-Id: I64b340d1c761bfd795a1a64dc2f7a831c8b2ff32
Reviewed-on: https://go-review.googlesource.com/87995
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
LewiGoddard pushed a commit to LewiGoddard/crypto that referenced this issue Feb 16, 2023
Rather than rounding the `type || X || Y` byte sequence to the next
8-bit boundary, packet.NewECDSAPublicKey() now rounds the X and Y
coordinates individually, then adds the bitlength 3 of type 4
(compressed). For NIST P-256, this leads to a bit length of 515,
rather than 520. GnuPG calculates 515 as well, and
https://tools.ietf.org/html/rfc6637#section-6 explicitly states that
"the exact size of the MPI payload is 515 bits for 'Curve P-256,'"
so the new formula is consistent.

Fixes golang/go#23460

Change-Id: I64b340d1c761bfd795a1a64dc2f7a831c8b2ff32
Reviewed-on: https://go-review.googlesource.com/87995
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
BiiChris pushed a commit to BiiChris/crypto that referenced this issue Sep 15, 2023
Rather than rounding the `type || X || Y` byte sequence to the next
8-bit boundary, packet.NewECDSAPublicKey() now rounds the X and Y
coordinates individually, then adds the bitlength 3 of type 4
(compressed). For NIST P-256, this leads to a bit length of 515,
rather than 520. GnuPG calculates 515 as well, and
https://tools.ietf.org/html/rfc6637#section-6 explicitly states that
"the exact size of the MPI payload is 515 bits for 'Curve P-256,'"
so the new formula is consistent.

Fixes golang/go#23460

Change-Id: I64b340d1c761bfd795a1a64dc2f7a831c8b2ff32
Reviewed-on: https://go-review.googlesource.com/87995
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants