Go: crypto/x509: ParsePKIXPublicKey can not parse 1024bit RSA

Created on 7 Dec 2017  路  8Comments  路  Source: golang/go

Please answer these questions before submitting your issue. Thanks!

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

go version go1.9.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/parazyd/go"
GORACE=""
GOROOT="/usr/lib/go"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="x86_64-gentoo-linux-musl-gcc"
GOGCCFLAGS="-fPIC -m64 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build264632172=/tmp/go-build -gno-record-gcc-switches"
CXX="x86_64-gentoo-linux-musl-g++"
CGO_ENABLED="0"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

https://play.golang.org/p/MPAwSqN2e7
Running with the former key from the official(?) example found at https://golang.org/pkg/crypto/x509/#ParsePKIXPublicKey works fine. However, when trying the same with a 1024-bit RSA public key, the program panics, being unable to parse it.

What did you expect to see?

pub is of type RSA:

What did you see instead?

panic: failed to parse DER encoded public key: asn1: structure error: tags don't match (16 vs {class:0 tag:2 length:129 isCompound:false}) {optional:false explicit:false application:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} AlgorithmIdentifier @3

goroutine 1 [running]:
main.main()
    /tmp/sandbox830663545/main.go:43 +0x3a0
FrozenDueToAge NeedsInvestigation

Most helpful comment

In Go 1.10, there will be a ParsePKCS1PublicKey that can do this. (They're rare, which is why the function hasn't existed prior to this. Normally they live inside a certificate.)

All 8 comments

The difference between both keys are not (only) the length of the prime of the rsa keys but the format. Only the first one is a PKIX key (asn1 sequence of AlgorithmIdentifier+BitString and the real key is in the BitString), the second key is a RSA public key (without the AlgorithmIdentifier).
You can see it that one is "-----BEGIN PUBLIC KEY-----", the other is "-----BEGIN RSA PUBLIC KEY-----".

@bpressure Removing "RSA" from the identifiers does not make a difference.

Of cause not, the RSA is an indicator that both keys are serialized in a different way.
The first one was serialized with

type pkixPublicKey struct {
    Algo      pkix.AlgorithmIdentifier
    BitString asn1.BitString
}

the second one with

type PublicKey struct {
    N *big.Int // modulus
    E int      // public exponent
}

This is working as intended, ParsePKIXPublicKey properly parses 1024-bit RSA keys that have an AlgorithmIdentifier and bitstring as @bpressure has explained.

This StackOverflow post also explains it in more detail.

Is there another way to parse such a key then?

@parazyd This issue tracker is not the place for questions, however I will say that you can use the encoding/asn1 package to parse keys that are encoded like that.

    const pubPEM = `-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALj23cgwEWD5R6P0SEqcOiKQkiIHaXuFKVZ3KEOb947ZRHqVPvB7It8V
0pZhit2nippBn7e7nUq/FjWVXsERyr98CYMoEWSwLv7rN7N4O0Evio8IPlK7maAG
rE0DPa61vTDm8qkJN1hYMQ0KQZYI2islND53N14NvOh8/lefIFsBAgMBAAE=
-----END RSA PUBLIC KEY-----`
    block, _ := pem.Decode([]byte(pubPEM))
    var pk rsa.PublicKey
    asn1.Unmarshal(block.Bytes, &pk)

In Go 1.10, there will be a ParsePKCS1PublicKey that can do this. (They're rare, which is why the function hasn't existed prior to this. Normally they live inside a certificate.)

Was this page helpful?
0 / 5 - 0 ratings