Skip to content

Commit d787eff

Browse files
committed
Move encoding types into their own file
1 parent a41773c commit d787eff

File tree

6 files changed

+187
-179
lines changed

6 files changed

+187
-179
lines changed

auth/utils/certificate_debug.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ func SignCertificateForTest(ctx context.Context, cert wallet.Certificate, signer
7272

7373
// Convert wallet.Certificate to certificates.Certificate for signing
7474
certObj := &certificates.Certificate{
75-
Type: wallet.Base64StringFromArray(encodedCert.Type),
76-
SerialNumber: wallet.Base64StringFromArray(encodedCert.SerialNumber),
75+
Type: wallet.StringBase64FromArray(encodedCert.Type),
76+
SerialNumber: wallet.StringBase64FromArray(encodedCert.SerialNumber),
7777
Fields: make(map[wallet.CertificateFieldNameUnder50Bytes]wallet.StringBase64),
7878
RevocationOutpoint: outpoint,
7979
}

auth/utils/get_verifiable_certificates_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ func TestGetVerifiableCertificates(t *testing.T) {
8888
if len(certs) > 0 {
8989
cert := certs[0]
9090
// Compare against base64 encoded values
91-
expectedTypeBase64 := wallet.Base64StringFromArray(certType1)
92-
expectedSerialBase64 := wallet.Base64StringFromArray(serial1)
91+
expectedTypeBase64 := wallet.StringBase64FromArray(certType1)
92+
expectedSerialBase64 := wallet.StringBase64FromArray(serial1)
9393
require.Equal(t, expectedTypeBase64, cert.Type)
9494
require.Equal(t, expectedSerialBase64, cert.SerialNumber)
9595
require.NotNil(t, cert.RevocationOutpoint)

identity/client.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ func (c *Client) PubliclyRevealAttributes(
8181
}
8282
// Convert Go certificate to Certificate instance to verify it
8383
masterCert := &certificates.Certificate{
84-
Type: wallet.Base64StringFromArray(certificate.Type),
85-
SerialNumber: wallet.Base64StringFromArray(certificate.SerialNumber),
84+
Type: wallet.StringBase64FromArray(certificate.Type),
85+
SerialNumber: wallet.StringBase64FromArray(certificate.SerialNumber),
8686
Subject: *certificate.Subject,
8787
Certifier: *certificate.Certifier,
8888
RevocationOutpoint: revocationOutpoint,
@@ -276,7 +276,7 @@ func (c *Client) parseIdentity(identity *wallet.IdentityCertificate) Displayable
276276
var name, avatarURL, badgeLabel, badgeIconURL, badgeClickURL string
277277

278278
// Parse out the name to display based on the specific certificate type which has clearly defined fields
279-
switch string(wallet.Base64StringFromArray(identity.Type)) {
279+
switch string(wallet.StringBase64FromArray(identity.Type)) {
280280
case KnownIdentityTypes.XCert:
281281
name = identity.DecryptedFields["userName"]
282282
avatarURL = identity.DecryptedFields["profilePhoto"]

wallet/encoding.go

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package wallet
2+
3+
import (
4+
"encoding/base64"
5+
"encoding/hex"
6+
"encoding/json"
7+
"fmt"
8+
ec "github.com/bsv-blockchain/go-sdk/primitives/ec"
9+
)
10+
11+
// BytesList is a custom type for JSON serialization of byte arrays that don't use base64 encoding.
12+
type BytesList []byte
13+
14+
func (s *BytesList) MarshalJSON() ([]byte, error) {
15+
// Marshal as a plain number array, not base64
16+
arr := make([]uint16, len(*s))
17+
for i, b := range *s {
18+
arr[i] = uint16(b)
19+
}
20+
return json.Marshal(arr)
21+
}
22+
23+
func (s *BytesList) UnmarshalJSON(data []byte) error {
24+
var temp []uint8
25+
if err := json.Unmarshal(data, &temp); err != nil {
26+
return err
27+
}
28+
*s = temp
29+
return nil
30+
}
31+
32+
// BytesHex is a helper type for marshaling byte slices as hex strings.
33+
type BytesHex []byte
34+
35+
// MarshalJSON implements the json.Marshaler interface.
36+
func (s BytesHex) MarshalJSON() ([]byte, error) {
37+
return json.Marshal(hex.EncodeToString(s))
38+
}
39+
40+
// UnmarshalJSON implements the json.Unmarshaler interface.
41+
func (s *BytesHex) UnmarshalJSON(data []byte) error {
42+
var str string
43+
if err := json.Unmarshal(data, &str); err != nil {
44+
return err
45+
}
46+
bytes, err := hex.DecodeString(str)
47+
if err != nil {
48+
return err
49+
}
50+
*s = bytes
51+
return nil
52+
}
53+
54+
type Bytes32Base64 [32]byte
55+
56+
func (b *Bytes32Base64) MarshalJSON() ([]byte, error) {
57+
s := base64.StdEncoding.EncodeToString(b[:])
58+
return json.Marshal(s)
59+
}
60+
61+
func (b *Bytes32Base64) UnmarshalJSON(data []byte) error {
62+
var s string
63+
if err := json.Unmarshal(data, &s); err != nil {
64+
return err
65+
}
66+
decoded, err := base64.StdEncoding.DecodeString(s)
67+
if err != nil {
68+
return err
69+
}
70+
if len(decoded) != 32 {
71+
return fmt.Errorf("expected 32 bytes, got %d", len(decoded))
72+
}
73+
copy(b[:], decoded)
74+
return nil
75+
}
76+
77+
type Bytes33Hex [33]byte
78+
79+
func (b *Bytes33Hex) MarshalJSON() ([]byte, error) {
80+
s := hex.EncodeToString(b[:])
81+
return json.Marshal(s)
82+
}
83+
84+
func (b *Bytes33Hex) UnmarshalJSON(data []byte) error {
85+
var s string
86+
if err := json.Unmarshal(data, &s); err != nil {
87+
return err
88+
}
89+
decoded, err := hex.DecodeString(s)
90+
if err != nil {
91+
return err
92+
}
93+
if len(decoded) != 33 {
94+
return fmt.Errorf("expected 33 bytes, got %d", len(decoded))
95+
}
96+
copy(b[:], decoded)
97+
return nil
98+
}
99+
100+
func BytesInHex33Slice(slice []Bytes33Hex, item []byte) bool {
101+
if len(item) > 33 {
102+
return false
103+
}
104+
var item33 Bytes33Hex
105+
copy(item33[:], item)
106+
for _, v := range slice {
107+
if v == item33 {
108+
return true
109+
}
110+
}
111+
return false
112+
}
113+
114+
// StringBase64 represents a string that should be base64 encoded in certain contexts.
115+
type StringBase64 string
116+
117+
func (s StringBase64) ToArray() ([32]byte, error) {
118+
b, err := base64.StdEncoding.DecodeString(string(s))
119+
if err != nil {
120+
return [32]byte{}, fmt.Errorf("error decoding base64 string: %w", err)
121+
}
122+
123+
var arr [32]byte
124+
if len(b) > 32 {
125+
return arr, fmt.Errorf("string too long: %d", len(b))
126+
}
127+
if len(b) == 0 {
128+
return arr, nil
129+
}
130+
copy(arr[:], b)
131+
return arr, nil
132+
}
133+
134+
func StringBase64FromArray(arr [32]byte) StringBase64 {
135+
return StringBase64(base64.StdEncoding.EncodeToString(arr[:]))
136+
}
137+
138+
// Signature is a wrapper around ec.Signature that provides custom JSON marshaling.
139+
// It serializes signatures as arrays of byte values rather than base64 strings.
140+
type Signature struct {
141+
ec.Signature
142+
}
143+
144+
// MarshalJSON implements the json.Marshaler interface for Signature.
145+
// It serializes the signature as an array of byte values.
146+
func (s *Signature) MarshalJSON() ([]byte, error) {
147+
sig := s.Serialize()
148+
sigInts := make([]uint16, len(sig))
149+
for i, b := range sig {
150+
sigInts[i] = uint16(b)
151+
}
152+
return json.Marshal(sigInts)
153+
}
154+
155+
// UnmarshalJSON implements the json.Unmarshaler interface for Signature.
156+
// It deserializes an array of byte values back into a signature.
157+
func (s *Signature) UnmarshalJSON(data []byte) error {
158+
var sigBytes []byte
159+
// Unmarshal directly from JSON array of numbers into byte slice
160+
if err := json.Unmarshal(data, &sigBytes); err != nil {
161+
return fmt.Errorf("could not unmarshal signature byte array: %w", err)
162+
}
163+
// Parse the raw bytes as DER.
164+
sig, err := ec.FromDER(sigBytes)
165+
if err != nil {
166+
return fmt.Errorf("could not parse signature from DER: %w", err)
167+
}
168+
s.Signature = *sig
169+
return nil
170+
}

wallet/interfaces.go

Lines changed: 0 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package wallet
22

33
import (
44
"context"
5-
"encoding/base64"
65
"encoding/hex"
76
"encoding/json"
87
"fmt"
@@ -429,49 +428,6 @@ type InternalizeOutput struct {
429428
InsertionRemittance *BasketInsertion `json:"insertionRemittance,omitempty"`
430429
}
431430

432-
// BytesList is a custom type for JSON serialization of byte arrays that don't use base64 encoding.
433-
type BytesList []byte
434-
435-
func (s *BytesList) MarshalJSON() ([]byte, error) {
436-
// Marshal as a plain number array, not base64
437-
arr := make([]uint16, len(*s))
438-
for i, b := range *s {
439-
arr[i] = uint16(b)
440-
}
441-
return json.Marshal(arr)
442-
}
443-
444-
func (s *BytesList) UnmarshalJSON(data []byte) error {
445-
var temp []uint8
446-
if err := json.Unmarshal(data, &temp); err != nil {
447-
return err
448-
}
449-
*s = temp
450-
return nil
451-
}
452-
453-
// BytesHex is a helper type for marshaling byte slices as hex strings.
454-
type BytesHex []byte
455-
456-
// MarshalJSON implements the json.Marshaler interface.
457-
func (s BytesHex) MarshalJSON() ([]byte, error) {
458-
return json.Marshal(hex.EncodeToString(s))
459-
}
460-
461-
// UnmarshalJSON implements the json.Unmarshaler interface.
462-
func (s *BytesHex) UnmarshalJSON(data []byte) error {
463-
var str string
464-
if err := json.Unmarshal(data, &str); err != nil {
465-
return err
466-
}
467-
bytes, err := hex.DecodeString(str)
468-
if err != nil {
469-
return err
470-
}
471-
*s = bytes
472-
return nil
473-
}
474-
475431
// InternalizeActionArgs contains data needed to import an external transaction into the wallet.
476432
type InternalizeActionArgs struct {
477433
Tx BytesList `json:"tx"` // BEEF encoded transaction, uint8 makes json.Marshall use numbers
@@ -886,90 +842,6 @@ type ProveCertificateResult struct {
886842
// Field names must be under 50 bytes to ensure efficient storage and processing.
887843
type CertificateFieldNameUnder50Bytes string
888844

889-
// StringBase64 represents a string that should be base64 encoded in certain contexts.
890-
type StringBase64 string
891-
892-
func (s StringBase64) ToArray() ([32]byte, error) {
893-
b, err := base64.StdEncoding.DecodeString(string(s))
894-
if err != nil {
895-
return [32]byte{}, fmt.Errorf("error decoding base64 string: %w", err)
896-
}
897-
898-
var arr [32]byte
899-
if len(b) > 32 {
900-
return arr, fmt.Errorf("string too long: %d", len(b))
901-
}
902-
if len(b) == 0 {
903-
return arr, nil
904-
}
905-
copy(arr[:], b)
906-
return arr, nil
907-
}
908-
909-
func Base64StringFromArray(arr [32]byte) StringBase64 {
910-
return StringBase64(base64.StdEncoding.EncodeToString(arr[:]))
911-
}
912-
913-
type Bytes32Base64 [32]byte
914-
915-
func (b *Bytes32Base64) MarshalJSON() ([]byte, error) {
916-
s := base64.StdEncoding.EncodeToString(b[:])
917-
return json.Marshal(s)
918-
}
919-
920-
func (b *Bytes32Base64) UnmarshalJSON(data []byte) error {
921-
var s string
922-
if err := json.Unmarshal(data, &s); err != nil {
923-
return err
924-
}
925-
decoded, err := base64.StdEncoding.DecodeString(s)
926-
if err != nil {
927-
return err
928-
}
929-
if len(decoded) != 32 {
930-
return fmt.Errorf("expected 32 bytes, got %d", len(decoded))
931-
}
932-
copy(b[:], decoded)
933-
return nil
934-
}
935-
936-
type Bytes33Hex [33]byte
937-
938-
func (b *Bytes33Hex) MarshalJSON() ([]byte, error) {
939-
s := hex.EncodeToString(b[:])
940-
return json.Marshal(s)
941-
}
942-
943-
func (b *Bytes33Hex) UnmarshalJSON(data []byte) error {
944-
var s string
945-
if err := json.Unmarshal(data, &s); err != nil {
946-
return err
947-
}
948-
decoded, err := hex.DecodeString(s)
949-
if err != nil {
950-
return err
951-
}
952-
if len(decoded) != 33 {
953-
return fmt.Errorf("expected 33 bytes, got %d", len(decoded))
954-
}
955-
copy(b[:], decoded)
956-
return nil
957-
}
958-
959-
func BytesInHex33Slice(slice []Bytes33Hex, item []byte) bool {
960-
if len(item) > 33 {
961-
return false
962-
}
963-
var item33 Bytes33Hex
964-
copy(item33[:], item)
965-
for _, v := range slice {
966-
if v == item33 {
967-
return true
968-
}
969-
}
970-
return false
971-
}
972-
973845
type Outpoint struct {
974846
Txid chainhash.Hash
975847
Index uint32

0 commit comments

Comments
 (0)