package x509
import (
)
var (
errInvalidOID = errors.New("invalid oid")
)
type OID struct {
der []byte
}
func ( string) (OID, error) {
var OID
return , .unmarshalOIDText()
}
func ( []byte) (OID, bool) {
if len() == 0 || [len()-1]&0x80 != 0 {
return OID{}, false
}
:= 0
for , := range {
if == && == 0x80 {
return OID{}, false
}
if &0x80 == 0 {
= + 1
}
}
return OID{}, true
}
func ( []uint64) (OID, error) {
if len() < 2 || [0] > 2 || ([0] < 2 && [1] >= 40) {
return OID{}, errInvalidOID
}
:= base128IntLength([0]*40 + [1])
for , := range [2:] {
+= base128IntLength()
}
:= make([]byte, 0, )
= appendBase128Int(, [0]*40+[1])
for , := range [2:] {
= appendBase128Int(, )
}
return OID{}, nil
}
func ( uint64) int {
if == 0 {
return 1
}
return (bits.Len64() + 6) / 7
}
func ( []byte, uint64) []byte {
for := base128IntLength() - 1; >= 0; -- {
:= byte( >> uint(*7))
&= 0x7f
if != 0 {
|= 0x80
}
= append(, )
}
return
}
func ( *big.Int) int {
if .Cmp(big.NewInt(0)) == 0 {
return 1
}
return (.BitLen() + 6) / 7
}
func ( []byte, *big.Int) []byte {
if .Cmp(big.NewInt(0)) == 0 {
return append(, 0)
}
for := base128BigIntLength() - 1; >= 0; -- {
:= byte(big.NewInt(0).Rsh(, uint()*7).Bits()[0])
&= 0x7f
if != 0 {
|= 0x80
}
= append(, )
}
return
}
func ( OID) ( []byte) ([]byte, error) {
return append(, .String()...), nil
}
func ( OID) () ([]byte, error) {
return .AppendText(nil)
}
func ( *OID) ( []byte) error {
return .unmarshalOIDText(string())
}
func ( *OID) ( string) error {
for , := range {
:= >= '0' && <= '9'
if ! && != '.' {
return errInvalidOID
}
}
var (
string
string
)
var bool
, , = strings.Cut(, ".")
if ! {
return errInvalidOID
}
, , = strings.Cut(, ".")
var (
= big.NewInt(0)
= big.NewInt(0)
)
if , := .SetString(, 10); ! {
return errInvalidOID
}
if , := .SetString(, 10); ! {
return errInvalidOID
}
if .Cmp(big.NewInt(2)) > 0 || (.Cmp(big.NewInt(2)) < 0 && .Cmp(big.NewInt(40)) >= 0) {
return errInvalidOID
}
:= .Mul(, big.NewInt(40))
.Add(, )
:= appendBase128BigInt(make([]byte, 0, 32), )
for {
var string
, , = strings.Cut(, ".")
, := big.NewInt(0).SetString(, 10)
if ! {
return errInvalidOID
}
= appendBase128BigInt(, )
}
.der =
return nil
}
func ( OID) ( []byte) ([]byte, error) {
return append(, .der...), nil
}
func ( OID) () ([]byte, error) {
return .AppendBinary(nil)
}
func ( *OID) ( []byte) error {
, := newOIDFromDER(bytes.Clone())
if ! {
return errInvalidOID
}
* =
return nil
}
func ( OID) ( OID) bool {
return bytes.Equal(.der, .der)
}
func ( []byte, int) (, int, bool) {
=
var int64
for := 0; < len(); ++ {
if == 5 {
= true
return
}
<<= 7
:= []
if == 0 && == 0x80 {
= true
return
}
|= int64( & 0x7f)
++
if &0x80 == 0 {
= int()
if > math.MaxInt32 {
= true
}
return
}
}
= true
return
}
func ( OID) ( asn1.ObjectIdentifier) bool {
if len() < 2 {
return false
}
, , := parseBase128Int(.der, 0)
if {
return false
}
if < 80 {
, := /40, %40
if [0] != || [1] != {
return false
}
} else {
, := 2, -80
if [0] != || [1] != {
return false
}
}
:= 2
for ; < len(.der); ++ {
, , = parseBase128Int(.der, )
if {
return false
}
if >= len() || != [] {
return false
}
}
return == len()
}
func ( OID) () string {
var strings.Builder
.Grow(32)
const (
= 64
= 7
= (1 << ( - )) - 1
)
var (
= 0
= uint64(0)
= make([]byte, 0, 21)
*big.Int
bool
)
for , := range .der {
:= & 0x7F
:= &0x80 == 0
if {
if != 0 {
.WriteByte('.')
}
}
if ! && > {
if == nil {
= new(big.Int)
}
= .SetUint64()
= true
}
if {
= .Lsh(, ).Or(, big.NewInt(int64()))
if {
if == 0 {
.WriteString("2.")
= .Sub(, big.NewInt(80))
}
= .Append(, 10)
.Write()
= [:0]
= 0
= + 1
= false
}
continue
}
<<=
|= uint64()
if {
if == 0 {
if < 80 {
.Write(strconv.AppendUint(, /40, 10))
.WriteByte('.')
.Write(strconv.AppendUint(, %40, 10))
} else {
.WriteString("2.")
.Write(strconv.AppendUint(, -80, 10))
}
} else {
.Write(strconv.AppendUint(, , 10))
}
= 0
= + 1
}
}
return .String()
}
func ( OID) () (asn1.ObjectIdentifier, bool) {
:= make([]int, 0, len(.der)+1)
const (
= 31
= 7
= (1 << ( - )) - 1
)
:= 0
for , := range .der {
if > {
return nil, false
}
<<=
|= int( & 0x7F)
if &0x80 == 0 {
if len() == 0 {
if < 80 {
= append(, /40)
= append(, %40)
} else {
= append(, 2)
= append(, -80)
}
= 0
continue
}
= append(, )
= 0
}
}
return , true
}