tools.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Package asn1tools provides tools for managing ASN1 marshaled data.
  2. package asn1tools
  3. import (
  4. "github.com/jcmturner/gofork/encoding/asn1"
  5. )
  6. // MarshalLengthBytes returns the ASN1 encoded bytes for the length 'l'
  7. //
  8. // There are two forms: short (for lengths between 0 and 127), and long definite (for lengths between 0 and 2^1008 -1).
  9. //
  10. // Short form: One octet. Bit 8 has value "0" and bits 7-1 give the length.
  11. //
  12. // Long form: Two to 127 octets. Bit 8 of first octet has value "1" and bits 7-1 give the number of additional length octets. Second and following octets give the length, base 256, most significant digit first.
  13. func MarshalLengthBytes(l int) []byte {
  14. if l <= 127 {
  15. return []byte{byte(l)}
  16. }
  17. var b []byte
  18. p := 1
  19. for i := 1; i < 127; {
  20. b = append([]byte{byte((l % (p * 256)) / p)}, b...)
  21. p = p * 256
  22. l = l - l%p
  23. if l <= 0 {
  24. break
  25. }
  26. }
  27. return append([]byte{byte(128 + len(b))}, b...)
  28. }
  29. // GetLengthFromASN returns the length of a slice of ASN1 encoded bytes from the ASN1 length header it contains.
  30. func GetLengthFromASN(b []byte) int {
  31. if int(b[1]) <= 127 {
  32. return int(b[1])
  33. }
  34. // The bytes that indicate the length
  35. lb := b[2 : 2+int(b[1])-128]
  36. base := 1
  37. l := 0
  38. for i := len(lb) - 1; i >= 0; i-- {
  39. l += int(lb[i]) * base
  40. base = base * 256
  41. }
  42. return l
  43. }
  44. // GetNumberBytesInLengthHeader returns the number of bytes in the ASn1 header that indicate the length.
  45. func GetNumberBytesInLengthHeader(b []byte) int {
  46. if int(b[1]) <= 127 {
  47. return 1
  48. }
  49. // The bytes that indicate the length
  50. return 1 + int(b[1]) - 128
  51. }
  52. // AddASNAppTag adds an ASN1 encoding application tag value to the raw bytes provided.
  53. func AddASNAppTag(b []byte, tag int) []byte {
  54. r := asn1.RawValue{
  55. Class: asn1.ClassApplication,
  56. IsCompound: true,
  57. Tag: tag,
  58. Bytes: b,
  59. }
  60. ab, _ := asn1.Marshal(r)
  61. return ab
  62. }
  63. /*
  64. // The Marshal method of golang's asn1 package does not enable you to define wrapping the output in an application tag.
  65. // This method adds that wrapping tag.
  66. func AddASNAppTag(b []byte, tag int) []byte {
  67. // The ASN1 wrapping consists of 2 bytes:
  68. // 1st byte -> Identifier Octet - Application Tag
  69. // 2nd byte -> The length (this will be the size indicated in the input bytes + 2 for the additional bytes we add here.
  70. // Application Tag:
  71. //| Bit: | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
  72. //| Value: | 0 | 1 | 1 | From the RFC spec 4120 |
  73. //| Explanation | Defined by the ASN1 encoding rules for an application tag | A value of 1 indicates a constructed type | The ASN Application tag value |
  74. // Therefore the value of the byte is an integer = ( Application tag value + 96 )
  75. //b = append(MarshalLengthBytes(int(b[1])+2), b...)
  76. b = append(MarshalLengthBytes(len(b)), b...)
  77. b = append([]byte{byte(96 + tag)}, b...)
  78. return b
  79. }
  80. */