简体   繁体   中英

Why is unmarshalling of a DER ASN.1 large integer limited to SEQUENCE in Golang?

I would like to be able to unmarshal a large integer from a DER file using the encoding/asn1 package, but it looks like it only works for a SEQUENCE of integers.

For example, this does not work, which is strange because the marshaling of the Big Int works well ( https://play.golang.org/p/Wkj0jAA6bpq ) :

package main

import (
    "encoding/asn1"
    "fmt"
    "math/big"
)


func main() {
        r, _ := new(big.Int).SetString("481B6A0913BD8024CA5D22F014F3", 16);
        encoding, _  := asn1.Marshal(r) 
        fmt.Printf("% X\n", encoding)               // Displayed as an integer: 02 0E 48 1B 6A 09 13 BD 80 24 CA 5D 22 F0 14 F3
        var t big.Int
        _, err := asn1.Unmarshal(encoding, &t)
        if err != nil {
            fmt.Println("Erreur unmarshalling -", err)  // asn1: structure error: tags don't match
        }   
        fmt.Println(t.String())
} 

It looks like I can unmarshall a large integer only if it's part of a SEQUENCE like in this example : https://play.golang.org/p/J93afvbk41L

package main

import (
    "encoding/asn1"
    "fmt"
    "math/big"
)

type TestBigInt struct {                    // From encoding/asn1/asn1_test.go
    X *big.Int
}

func main() {
        r, _ := new(big.Int).SetString("481B6A0913BD8024CA5D22F014F3", 16);
        encoding, _  := asn1.Marshal(TestBigInt{r}) 
        fmt.Printf("% X\n", encoding)               // Displayed as a sequence of an integer: 30 10 02 0E 48 1B 6A 09 13 BD 80 24 CA 5D 22 F0 14 F3
        var t TestBigInt
        _, err := asn1.Unmarshal(encoding, &t)
        if err != nil {
            fmt.Println("Erreur unmarshalling -", err)  
        }   
        fmt.Println(t.X.String())
} 

However, it works well for 32 bits of 64 bits integer like in this example : https://play.golang.org/p/vcIgWrI-sk-

package main

import (
    "encoding/asn1"
    "fmt"
)

func main() {
        r := 12234
        encoding, _ := asn1.Marshal(r)
        fmt.Printf("% X\n", encoding)
        var t int
        _, err := asn1.Unmarshal(encoding, &t)
        if err != nil {
            fmt.Println("Erreur unmarshalling -", err)
        }   
        fmt.Println(t)
}

Is this a known limitation of the encoding/asn1 package ? Any known solution to unmarshal a large integer outside a SEQUENCE ?

The documentation states that:

An ASN.1 INTEGER can be written to an int, int32, int64, or *big.Int (from the math/big package).

Note that the fourth option is a *big.Int , not a big.Int . You can't see it because of the auto type deduction, but the former is actually the same type as r in your first example, and more clearly the type of X in your second example, too.

If you change your variable to a pointer, then it should work. For example, modifying your first example:

package main

import (
    "encoding/asn1"
    "fmt"
    "math/big"
)


func main() {
        r, _ := new(big.Int).SetString("481B6A0913BD8024CA5D22F014F3", 16);
        encoding, _  := asn1.Marshal(r) 
        fmt.Printf("% X\n", encoding)

        var t *big.Int  // <---- changed type
        _, err := asn1.Unmarshal(encoding, &t)
        if err != nil {
            fmt.Println("Erreur unmarshalling -", err)
        }   

        fmt.Println(t.String())
} 

yields:

paul@horus:asn1int$ ./asn1int
02 0E 48 1B 6A 09 13 BD 80 24 CA 5D 22 F0 14 F3
1462505468235399478280266926003443
paul@horus:asn1int$

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM