Skip to content

proposal: crypto/x509: provide function to convert from x509.OID to asn1.ObjectIdentifier #81363

Open

Description

@RufusJWB

Proposal Details

The new OID type in the x509 package contains a function to convert from asn1.ObjectIdentifier to the new OID type. It would be helpful to have a reverse function as well as part of this package. It could look like the following:

func ASN1OIDFromOID(oid x509.OID) asn1.ObjectIdentifier {
	parts := strings.Split(oid.String(), ".")
	result := make(asn1.ObjectIdentifier, len(parts))
	for i, part := range parts {
		component, err := strconv.Atoi(part)
		if err != nil {
			panic(err)
		}
		result[i] = component
	}
	return result
}

Activity

  1. added this to the Proposal milestone on Sep 4, 2026
  2. mateusz834 commented on Sep 5, 2026

    @mateusz834
    Member

    It would have to return either a bool or an error, since OID supports elements > 31bits, whereas asn1.ObjectIdentifier does not not. I think bool would be enough here, since there is only a single error condition.

  3. FiloSottile commented on Sep 5, 2026

    @FiloSottile
    Contributor

    Not necessarily opposed, but where do you need the asn1.ObjectIdentifier? Because ideally we'd instead add support for x509.OID there.

  4. RufusJWB commented on Sep 5, 2026

    @RufusJWB
    Author

    Not necessarily opposed, but where do you need the asn1.ObjectIdentifier? Because ideally we'd instead add support for x509.OID there.

    encoding/asn1 fails when marshalling a x509.oid. Please see the following repros:

    package main
    
    import (
    	"crypto/x509"
    	"encoding/asn1"
    	"fmt"
    	"testing"
    )
    
    // Showcase that encoding/asn1 cannot marshal crypto/x509.OID directly.
    func TestX509OIDASN1MarshalError(t *testing.T) {
    	oid, _ := x509.OIDFromInts([]uint64{1, 2, 840, 113533, 7, 66, 13})
    
    	encoded, err := asn1.Marshal(oid)
    	if err == nil {
    		fmt.Printf("Encoded ASN.1 data: %x\n", encoded)
    		t.Fatal("expected asn1.Marshal to fail when given x509.OID, but it succeeded")
    	}
    
    	fmt.Printf("Error when marshaling x509.OID with encoding/asn1:\n  %v\n", err)
    }
    
    // Showcase that encoding/asn1 can marshal asn1.ObjectIdentifier directly.
    func TestASN1ObjectIdentifierMarshalSuccess(t *testing.T) {
    	oid := asn1.ObjectIdentifier{1, 2, 840, 113533, 7, 66, 13}
    
    	encoded, err := asn1.Marshal(oid)
    	if err != nil {
    		t.Fatalf("asn1.Marshal failed: %v", err)
    	}
    
    	fmt.Printf("Successfully marshaled asn1.ObjectIdentifier with encoding/asn1\n")
    	fmt.Printf("Encoded ASN.1 data: %x\n", encoded)
    }

    This is especially annoying since OIDs and ASN.1 are closely related with each other.

  5. RufusJWB commented on Sep 10, 2026

    @RufusJWB
    Author

    @FiloSottile do you think we could strive to enhance the https://pkg.go.dev/encoding/asn1#Marshal function to support also x509.OIDs?

  6. mateusz834 commented on Sep 10, 2026

    @mateusz834
    Member

    No, since this would cause a circular dep. We could move OID to asn1 and make x509.OID an alias though.

  7. FiloSottile commented on Sep 10, 2026

    @FiloSottile
    Contributor

    I mean, we could cheat, like asserting against

    interface {
        EqualASN1OID(other asn1.ObjectIdentifier) bool
        MarshalBinary() ([]byte, error)
    }
    

    and go from there.

    It definitely is surprising that encoding/asn1 can't encode crypto/x509.OID.

  8. mateusz834 commented on Sep 10, 2026

    @mateusz834
    Member

    we could cheat

    I think we could also cheat by moving OID to an internal package and making crypto.X509 an alias to it.

  9. FiloSottile commented on Sep 10, 2026

    @FiloSottile
    Contributor

    Yeah but that makes the methods move to the internal package's godoc page.

  10. RufusJWB commented on Sep 24, 2026

    @RufusJWB
    Author

    how would we proceed with this topic?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions