You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
3.9 KiB

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