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

bitLength not correct, and ECDH privateKey load with GPG is wrong #39

Closed
izouxv opened this issue Nov 7, 2019 · 4 comments
Closed

bitLength not correct, and ECDH privateKey load with GPG is wrong #39

izouxv opened this issue Nov 7, 2019 · 4 comments

Comments

@izouxv
Copy link
Contributor

izouxv commented Nov 7, 2019

Hi
there are two bugs in this test case
1: bitlength error, when i generate entity with EdDSA, and the subkey bitlength is wrong. its 263, not 256
2: ouput this key to one asc file, and then , import the file with "gpg --import", its wrong. public key is ok, primary key is error
i tested ouput with password, and without password, it all wrong.
ONLY WITH ECDH

main test funcation

func TestOpenPGP_ExportECDH_GPGImport(t *testing.T) {
	entity, err := openpgp.NewEntity("name", "comment", "email@email.com", config)
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	bitlen, err := entity.Subkeys[0].PublicKey.BitLength()
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if bitlen != 256 {
		t.Logf("!!! ERROR bitlen: %v: \n", bitlen)
	}

	pgpg, _ := exportGPG(entity)
	t.Fatalf("!!! ERROR, gpg --import with this file will ERROR: \n%v", pgpg)
}

ENV

go version go1.13.1 darwin/amd64
gpg (GnuPG) 2.2.16
libgcrypt 1.8.4
mac10.15

openpgp_test.go.zip

@izouxv izouxv changed the title ECDH output to file will, and gpg import will error bitLength not correct, and ECDH privateKey load with GPG is wrong Nov 7, 2019
@zugzwang
Copy link
Contributor

zugzwang commented Nov 7, 2019

Hello again @izouxv!
Thanks for the issue. I will look into this.

@zugzwang
Copy link
Contributor

zugzwang commented Nov 7, 2019

I confirm the results of your test function with

go version go1.13.4 linux/amd64
gpg (GnuPG) 2.2.12
Ubuntu 19.04

@zugzwang
Copy link
Contributor

zugzwang commented Nov 7, 2019

I also confirm

  • The correctness of gpg --import with a key generated in Go with PubKeyAlgoRSA in config.
  • The correctness of importing a PubKeyAlsoEdDSA key (generated with Go) into Go, with ReadArmoredKeyRing.
  • The correctness of importing a EdDSA key (generated with gpg) with ReadArmoredKeyRing, into Go.

For the last bullet, the key was generated with

gpg --expert --full-gen-key

With the options:

(9) ECC and ECC
(1) Curve 25519
0 = key does not expire
No password

@zugzwang
Copy link
Contributor

zugzwang commented Nov 7, 2019

@izouxv, thanks a lot for bringing this up.

2.

The issue is that the current PrivateKey.SerializeUnEncrypted function (private_key.go) is missing the EdDSA case and the error checking, so it didn't serialize the private key and the error went undetected.

It should be fixed now in #40, and also the ed25519 keys were stored unmasked, which is an error and makes gpg to interpret them as encrypted.

I checked that your test is passing now (i.e., the private key you're printing in Fatalf can be correctly imported into gpg).

// (first fetch #40)
// Get your test file
wget https://github.com/ProtonMail/crypto/files/3819150/openpgp_test.go.zip
unzip openpgp_test.go.zip
go test -run TestOpenPGP_ExportECDH_GPGImport
// (write output key to file goExportedEd25519.asc)
// Import into gpg
gpg --import goExportedEd25519.asc

1.

About the bitLength error, it's completely normal that the length of the subkey is 263. For instance, I checked that a key imported from gpg also has this bit length. The reason is (from RFC4880bis):

   The EdDSA algorithm defines a specific point compression format.  To
   indicate the use of this compression format and to make sure that the
   key can be represented in the Multiprecision Integer (MPI) format the
   octet string specifying the point is prefixed with the octet 0x40.
   This encoding is an extension of the encoding given in [SEC1] which
   uses 0x04 to indicate an uncompressed point.

   For example, the length of a public key for the curve Ed25519 is 263
   bit: 7 bit to represent the 0x40 prefix octet and 32 octets for the
   native value of the public key.

This issue was closed.
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

No branches or pull requests

2 participants