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  }