cryptobyte: add uint48 methods Adds uint48 methods for cryptobyte.Builder and cryptobyte.String. Supporting 48-bit unsigned integers is useful for working with protocols that use them for sequence numbers, such as DTLS. Fixes golang/go#61275 Change-Id: Ibe49422d37644b9212b28b123dc5e01850f7b05b GitHub-Last-Rev: 11b388c240109c8f4ac23880645c901ce6d2f093 GitHub-Pull-Request: golang/crypto#265 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/508675 Reviewed-by: Roland Shoemaker <roland@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: qiulaidongfeng <2645477756@qq.com> Run-TryBot: Roland Shoemaker <roland@golang.org> Auto-Submit: Roland Shoemaker <roland@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/cryptobyte/builder.go b/cryptobyte/builder.go index c05ac7d..cf254f5 100644 --- a/cryptobyte/builder.go +++ b/cryptobyte/builder.go
@@ -95,6 +95,11 @@ b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) } +// AddUint48 appends a big-endian, 48-bit value to the byte string. +func (b *Builder) AddUint48(v uint64) { + b.add(byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + // AddUint64 appends a big-endian, 64-bit value to the byte string. func (b *Builder) AddUint64(v uint64) { b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
diff --git a/cryptobyte/cryptobyte_test.go b/cryptobyte/cryptobyte_test.go index dc90e81..9b55d52 100644 --- a/cryptobyte/cryptobyte_test.go +++ b/cryptobyte/cryptobyte_test.go
@@ -179,6 +179,27 @@ } } +func TestUint48(t *testing.T) { + var b Builder + var u uint64 = 0xfefcff3cfdfc + b.AddUint48(u) + if err := builderBytesEq(&b, 254, 252, 255, 60, 253, 252); err != nil { + t.Error(err) + } + + var s String = b.BytesOrPanic() + var v uint64 + if !s.ReadUint48(&v) { + t.Error("ReadUint48() = false, want true") + } + if v != u { + t.Errorf("v = %x, want %x", v, u) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + func TestUint64(t *testing.T) { var b Builder b.AddUint64(0xf2fefefcff3cfdfc)
diff --git a/cryptobyte/string.go b/cryptobyte/string.go index 0531a3d..10692a8 100644 --- a/cryptobyte/string.go +++ b/cryptobyte/string.go
@@ -81,6 +81,17 @@ return true } +// ReadUint48 decodes a big-endian, 48-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint48(out *uint64) bool { + v := s.read(6) + if v == nil { + return false + } + *out = uint64(v[0])<<40 | uint64(v[1])<<32 | uint64(v[2])<<24 | uint64(v[3])<<16 | uint64(v[4])<<8 | uint64(v[5]) + return true +} + // ReadUint64 decodes a big-endian, 64-bit value into out and advances over it. // It reports whether the read was successful. func (s *String) ReadUint64(out *uint64) bool {