github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/x/crypto/cryptobyte/example_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cryptobyte_test 6 7 import ( 8 "errors" 9 "fmt" 10 11 "github.com/icodeface/tls/internal/x/crypto/cryptobyte" 12 "github.com/icodeface/tls/internal/x/crypto/cryptobyte/asn1" 13 ) 14 15 func ExampleString_lengthPrefixed() { 16 // This is an example of parsing length-prefixed data (as found in, for 17 // example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed 18 // strings. 19 20 input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'}) 21 var result []string 22 23 var values cryptobyte.String 24 if !input.ReadUint16LengthPrefixed(&values) || 25 !input.Empty() { 26 panic("bad format") 27 } 28 29 for !values.Empty() { 30 var value cryptobyte.String 31 if !values.ReadUint8LengthPrefixed(&value) { 32 panic("bad format") 33 } 34 35 result = append(result, string(value)) 36 } 37 38 // Output: []string{"hello", "world"} 39 fmt.Printf("%#v\n", result) 40 } 41 42 func ExampleString_aSN1() { 43 // This is an example of parsing ASN.1 data that looks like: 44 // Foo ::= SEQUENCE { 45 // version [6] INTEGER DEFAULT 0 46 // data OCTET STRING 47 // } 48 49 input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'}) 50 51 var ( 52 version int64 53 data, inner, versionBytes cryptobyte.String 54 haveVersion bool 55 ) 56 if !input.ReadASN1(&inner, asn1.SEQUENCE) || 57 !input.Empty() || 58 !inner.ReadOptionalASN1(&versionBytes, &haveVersion, asn1.Tag(6).Constructed().ContextSpecific()) || 59 (haveVersion && !versionBytes.ReadASN1Integer(&version)) || 60 (haveVersion && !versionBytes.Empty()) || 61 !inner.ReadASN1(&data, asn1.OCTET_STRING) || 62 !inner.Empty() { 63 panic("bad format") 64 } 65 66 // Output: haveVersion: true, version: 2, data: hello 67 fmt.Printf("haveVersion: %t, version: %d, data: %s\n", haveVersion, version, string(data)) 68 } 69 70 func ExampleBuilder_aSN1() { 71 // This is an example of building ASN.1 data that looks like: 72 // Foo ::= SEQUENCE { 73 // version [6] INTEGER DEFAULT 0 74 // data OCTET STRING 75 // } 76 77 version := int64(2) 78 data := []byte("hello") 79 const defaultVersion = 0 80 81 var b cryptobyte.Builder 82 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { 83 if version != defaultVersion { 84 b.AddASN1(asn1.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) { 85 b.AddASN1Int64(version) 86 }) 87 } 88 b.AddASN1OctetString(data) 89 }) 90 91 result, err := b.Bytes() 92 if err != nil { 93 panic(err) 94 } 95 96 // Output: 300ca603020102040568656c6c6f 97 fmt.Printf("%x\n", result) 98 } 99 100 func ExampleBuilder_lengthPrefixed() { 101 // This is an example of building length-prefixed data (as found in, 102 // for example, TLS). Imagine a 16-bit prefixed series of 8-bit 103 // prefixed strings. 104 input := []string{"hello", "world"} 105 106 var b cryptobyte.Builder 107 b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { 108 for _, value := range input { 109 b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { 110 b.AddBytes([]byte(value)) 111 }) 112 } 113 }) 114 115 result, err := b.Bytes() 116 if err != nil { 117 panic(err) 118 } 119 120 // Output: 000c0568656c6c6f05776f726c64 121 fmt.Printf("%x\n", result) 122 } 123 124 func ExampleBuilder_lengthPrefixOverflow() { 125 // Writing more data that can be expressed by the length prefix results 126 // in an error from Bytes(). 127 128 tooLarge := make([]byte, 256) 129 130 var b cryptobyte.Builder 131 b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { 132 b.AddBytes(tooLarge) 133 }) 134 135 result, err := b.Bytes() 136 fmt.Printf("len=%d err=%s\n", len(result), err) 137 138 // Output: len=0 err=cryptobyte: pending child length 256 exceeds 1-byte length prefix 139 } 140 141 func ExampleBuilderContinuation_errorHandling() { 142 var b cryptobyte.Builder 143 // Continuations that panic with a BuildError will cause Bytes to 144 // return the inner error. 145 b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { 146 b.AddUint32(0) 147 panic(cryptobyte.BuildError{Err: errors.New("example error")}) 148 }) 149 150 result, err := b.Bytes() 151 fmt.Printf("len=%d err=%s\n", len(result), err) 152 153 // Output: len=0 err=example error 154 }