-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.go
120 lines (97 loc) · 2.7 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package ocmf_go
import (
"encoding/json"
"strings"
"github.com/pkg/errors"
)
var (
ErrInvalidFormat = errors.New("invalid OCMF message format")
ErrVerificationFailure = errors.New("verification failed")
ErrPayloadEmpty = errors.New("payload is empty")
)
type Parser struct {
payload *PayloadSection
signature *Signature
opts ParserOpts
err error
}
func NewParser(opts ...Opt) *Parser {
defaults := defaultOpts()
// Apply opts
for _, opt := range opts {
opt(&defaults)
}
return &Parser{
opts: defaults,
}
}
// ParseOcmfMessageFromString Returns a new Parser instance with the payload and signature fields set
func (p *Parser) ParseOcmfMessageFromString(data string) *Parser {
payloadSection, signature, err := parseOcmfMessageFromString(data)
if err != nil {
return &Parser{err: err, opts: p.opts}
}
return &Parser{
payload: payloadSection,
signature: signature,
opts: p.opts,
}
}
func (p *Parser) GetPayload() (*PayloadSection, error) {
if p.err != nil {
return nil, p.err
}
// Validate the payload if automatic validation is enabled
if p.opts.withAutomaticValidation {
if err := p.payload.Validate(); err != nil {
return nil, errors.Wrap(err, "payload validation failed")
}
}
return p.payload, nil
}
func (p *Parser) GetSignature() (*Signature, error) {
if p.err != nil {
return nil, p.err
}
// Validate the signature if automatic validation is enabled
if p.opts.withAutomaticValidation {
if err := p.signature.Validate(); err != nil {
return nil, errors.Wrap(err, "signature validation failed")
}
}
if p.opts.withAutomaticSignatureVerification {
if p.payload == nil {
return nil, ErrPayloadEmpty
}
valid, err := p.signature.Verify(*p.payload, p.opts.publicKey)
if err != nil {
return nil, errors.Wrap(err, "unable to verify signature")
}
// Even if the signature is valid, we still return an error if the verification failed
if !valid {
return p.signature, ErrVerificationFailure
}
}
return p.signature, nil
}
func parseOcmfMessageFromString(data string) (*PayloadSection, *Signature, error) {
if !strings.HasPrefix(data, "OCMF|") {
return nil, nil, ErrInvalidFormat
}
data, _ = strings.CutPrefix(data, "OCMF|")
splitData := strings.Split(data, "|")
if len(splitData) != 2 {
return nil, nil, ErrInvalidFormat
}
payloadSection := PayloadSection{}
err := json.Unmarshal([]byte(splitData[0]), &payloadSection)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to unmarshal payload")
}
signature := Signature{}
err = json.Unmarshal([]byte(splitData[1]), &signature)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to unmarshal signature")
}
return &payloadSection, &signature, nil
}