-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
7 changed files
with
236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
BSD 3-Clause License | ||
|
||
Copyright (c) 2023, Alexander Yastrebov | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
2. Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
3. Neither the name of the copyright holder nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Read 64bit ASN1 ObjectIdentifier | ||
|
||
This is a fork of `golang.org/x/crypto/cryptobyte` [String.ReadASN1ObjectIdentifier](https://pkg.go.dev/golang.org/x/crypto/cryptobyte#String.ReadASN1ObjectIdentifier) that supports 64 bit identifiers. | ||
|
||
See | ||
* [example_test.go](example_test.go) | ||
* https://github.com/golang/go/issues/58821 | ||
|
||
```sh | ||
# supported | ||
~$ echo '2^63-1' | bc | ||
9223372036854775807 | ||
|
||
~$ openssl asn1parse -genstr 'OID:2.5.2.9223372036854775807' -out - | hexdump -C | ||
00000000 06 0b 55 02 ff ff ff ff ff ff ff ff 7f 20 20 20 |..U.......... | | ||
00000010 20 30 3a 64 3d 30 20 20 68 6c 3d 32 20 6c 3d 20 | 0:d=0 hl=2 l= | | ||
00000020 20 31 31 20 70 72 69 6d 3a 20 4f 42 4a 45 43 54 | 11 prim: OBJECT| | ||
00000030 20 20 20 20 20 20 20 20 20 20 20 20 3a 32 2e 35 | :2.5| | ||
00000040 2e 32 2e 39 32 32 33 33 37 32 30 33 36 38 35 34 |.2.9223372036854| | ||
00000050 37 37 35 38 30 37 0a |775807.| | ||
00000057 | ||
|
||
# unsupported | ||
~$ echo '2^63' | bc | ||
9223372036854775808 | ||
|
||
~$ openssl asn1parse -genstr 'OID:2.5.2.9223372036854775808' -out - | hexdump -C | ||
00000000 06 0c 55 02 81 80 80 80 80 80 80 80 80 00 20 20 |..U........... | | ||
00000010 20 20 30 3a 64 3d 30 20 20 68 6c 3d 32 20 6c 3d | 0:d=0 hl=2 l=| | ||
00000020 20 20 31 32 20 70 72 69 6d 3a 20 4f 42 4a 45 43 | 12 prim: OBJEC| | ||
00000030 54 20 20 20 20 20 20 20 20 20 20 20 20 3a 32 2e |T :2.| | ||
00000040 35 2e 32 2e 39 32 32 33 33 37 32 30 33 36 38 35 |5.2.922337203685| | ||
00000050 34 37 37 35 38 30 38 0a |4775808.| | ||
00000058 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package asn1oid64_test | ||
|
||
import ( | ||
encoding_asn1 "encoding/asn1" | ||
"fmt" | ||
|
||
"golang.org/x/crypto/cryptobyte" | ||
|
||
"github.com/AlexanderYastrebov/asn1oid64" | ||
) | ||
|
||
func ExampleReadASN1ObjectIdentifier() { | ||
encoded, err := encoding_asn1.Marshal(encoding_asn1.ObjectIdentifier([]int{2, 5, 2, 9223372036854775807})) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
in := cryptobyte.String(encoded) | ||
|
||
var out encoding_asn1.ObjectIdentifier | ||
ok := asn1oid64.ReadASN1ObjectIdentifier(&in, &out) | ||
|
||
fmt.Printf("%s %t", out, ok) | ||
|
||
// Output: | ||
// 2.5.2.9223372036854775807 true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module github.com/AlexanderYastrebov/asn1oid64 | ||
|
||
go 1.19 | ||
|
||
require golang.org/x/crypto v0.7.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= | ||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package asn1oid64 | ||
|
||
import ( | ||
encoding_asn1 "encoding/asn1" | ||
"math" | ||
|
||
"golang.org/x/crypto/cryptobyte" | ||
"golang.org/x/crypto/cryptobyte/asn1" | ||
) | ||
|
||
// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and | ||
// advances. It reports whether the read was successful. | ||
func ReadASN1ObjectIdentifier(s *cryptobyte.String, out *encoding_asn1.ObjectIdentifier) bool { | ||
var bytes cryptobyte.String | ||
if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { | ||
return false | ||
} | ||
|
||
// In the worst case, we get two elements from the first byte (which is | ||
// encoded differently) and then every varint is a single byte long. | ||
components := make([]int, len(bytes)+1) | ||
|
||
// The first varint is 40*value1 + value2: | ||
// According to this packing, value1 can take the values 0, 1 and 2 only. | ||
// When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, | ||
// then there are no restrictions on value2. | ||
var v int | ||
if !readBase128Int(&bytes, &v) { | ||
return false | ||
} | ||
if v < 80 { | ||
components[0] = v / 40 | ||
components[1] = v % 40 | ||
} else { | ||
components[0] = 2 | ||
components[1] = v - 80 | ||
} | ||
|
||
i := 2 | ||
for ; len(bytes) > 0; i++ { | ||
if !readBase128Int(&bytes, &v) { | ||
return false | ||
} | ||
components[i] = v | ||
} | ||
*out = components[:i] | ||
return true | ||
} | ||
|
||
func readBase128Int(s *cryptobyte.String, out *int) bool { | ||
ret := 0 | ||
for i := 0; len(*s) > 0; i++ { | ||
if ret > math.MaxInt>>7 { | ||
return false | ||
} | ||
// if i == 5 { | ||
// return false | ||
// } | ||
// // Avoid overflowing int on a 32-bit platform. | ||
// // We don't want different behavior based on the architecture. | ||
// if ret >= 1<<(31-7) { | ||
// return false | ||
// } | ||
ret <<= 7 | ||
b := read(s, 1)[0] | ||
ret |= int(b & 0x7f) | ||
if b&0x80 == 0 { | ||
*out = ret | ||
return true | ||
} | ||
} | ||
return false // truncated | ||
} | ||
|
||
func read(s *cryptobyte.String, n int) []byte { | ||
if len(*s) < n || n < 0 { | ||
return nil | ||
} | ||
v := (*s)[:n] | ||
*s = (*s)[n:] | ||
return v | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package asn1oid64_test | ||
|
||
import ( | ||
"bytes" | ||
encoding_asn1 "encoding/asn1" | ||
"testing" | ||
|
||
"golang.org/x/crypto/cryptobyte" | ||
|
||
"github.com/AlexanderYastrebov/asn1oid64" | ||
) | ||
|
||
func TestASN1ObjectIdentifier(t *testing.T) { | ||
testData := []struct { | ||
in []byte | ||
ok bool | ||
out []int | ||
}{ | ||
{[]byte{}, false, []int{}}, | ||
{[]byte{6, 0}, false, []int{}}, | ||
{[]byte{5, 1, 85}, false, []int{2, 5}}, | ||
{[]byte{6, 1, 85}, true, []int{2, 5}}, | ||
{[]byte{6, 2, 85, 0x02}, true, []int{2, 5, 2}}, | ||
{[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}}, | ||
{[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}}, | ||
{[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}}, | ||
{[]byte{6, 7, 85, 0x02, 0x85, 0xc7, 0xcc, 0xfb, 0x01}, true, []int{2, 5, 2, 1492336001}}, | ||
{[]byte{6, 7, 0x55, 0x02, 0x87, 0xff, 0xff, 0xff, 0x7f}, true, []int{2, 5, 2, 2147483647}}, // 2**31-1 | ||
{[]byte{6, 7, 0x55, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00}, true, []int{2, 5, 2, 2147483648}}, // 2**31 | ||
{[]byte{6, 11, 0x2a, 0x24, 0xcb, 0x89, 0x90, 0x82, 0x1e, 0x03, 0x01, 0x01, 0x01}, true, []int{1, 2, 36, 20151795998, 3, 1, 1, 1}}, // https://github.com/golang/go/issues/58821 | ||
{[]byte{6, 11, 0x55, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, true, []int{2, 5, 2, 9223372036854775807}}, // 2**63-1 | ||
{[]byte{0, 12, 0x55, 0x02, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00}, false, []int{}}, // 2**63 | ||
} | ||
|
||
for i, test := range testData { | ||
in := cryptobyte.String(test.in) | ||
var out encoding_asn1.ObjectIdentifier | ||
ok := asn1oid64.ReadASN1ObjectIdentifier(&in, &out) | ||
if ok != test.ok || ok && !out.Equal(test.out) { | ||
t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) | ||
continue | ||
} | ||
|
||
var b cryptobyte.Builder | ||
b.AddASN1ObjectIdentifier(out) | ||
result, err := b.Bytes() | ||
if builderOk := err == nil; test.ok != builderOk { | ||
t.Errorf("#%d: error from Builder.Bytes: %s", i, err) | ||
continue | ||
} | ||
if test.ok && !bytes.Equal(result, test.in) { | ||
t.Errorf("#%d: reserialisation didn't match, got %x, want %x", i, result, test.in) | ||
continue | ||
} | ||
} | ||
} |