* test commit * delete test commit * signing plugin - changes for review * Initial commit : beckn Signing Plugin Module * Added verification plugin post review discussion with leads below changes are made 1. Commented out the signature expiration validation code for both the signing and verification plugins. will update it based on the confirmation. * Create signing_plugin_test.go Added Test Cases for Signing Plugin * Signing and Verification Plugin Added signing plugin and verification plugin with the unit test cases, achieving the following code coverage Signing Plugin : 91.9% Verification Plugin : 92.3% * Added plugin.go to handle the dynamic loading and usage of the plugin implementation * Update the code to meet the linting standards * Added Test Cases for plugin.go 1.Added test cases for plugin.go for both signer and verifier. 2.Added new Function Close to release the resources (mock implementation) 3.Fixed camelCase Issue. * Updated the code coverage for signing plugin Raised code coverage from 85 to 92 for signing plugin * Changes for review Comments 1. updated directory names from Signer to signer 2. Updated Verifier plugin to take header value 3. Updated the config to use a pointer in the signing plugin * Updated directory name for signer and verifier * Removed the Duplicate directories Signer and Verifier * Updated the code to pass the timestamp as a parameter for the signing plugin * Updates on the review comments * Update on the Review Comments * Test commit for code coverage * Update on the review Comments 1. Renaming of NewSigner to New 2. Removed of .so files. 3. Removed external libraries. * Test commit for code coverage * udpate as per the golint standards * update on the code review comments 1. Rename of Validator to Verifier 2. Removed as a pointer for plugins 3. comment updated for Signer * Test Commit for the code coverage * test commit for code coverage * test commit for code coverage * test commit for code coverage * updated code on review comments * update on review comments * update on review comments --------- Co-authored-by: mohit3367 <mohitkatare4@gmail.com>
121 lines
3.8 KiB
Go
121 lines
3.8 KiB
Go
package verifier
|
|
|
|
import (
|
|
"context"
|
|
"crypto/ed25519"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"golang.org/x/crypto/blake2b"
|
|
)
|
|
|
|
// Config struct for Verifier.
|
|
type Config struct {
|
|
}
|
|
|
|
// Verifier implements the Verifier interface.
|
|
type Verifier struct {
|
|
config *Config
|
|
}
|
|
|
|
// New creates a new Verifier instance.
|
|
func New(ctx context.Context, config *Config) (*Verifier, func() error, error) {
|
|
v := &Verifier{config: config}
|
|
|
|
return v, v.Close, nil
|
|
}
|
|
|
|
// Verify checks the signature for the given payload and public key.
|
|
func (v *Verifier) Verify(ctx context.Context, body []byte, header []byte, publicKeyBase64 string) (bool, error) {
|
|
createdTimestamp, expiredTimestamp, signature, err := parseAuthHeader(string(header))
|
|
if err != nil {
|
|
// TODO: Return appropriate error code when Error Code Handling Module is ready
|
|
return false, fmt.Errorf("error parsing header: %w", err)
|
|
}
|
|
|
|
signatureBytes, err := base64.StdEncoding.DecodeString(signature)
|
|
if err != nil {
|
|
// TODO: Return appropriate error code when Error Code Handling Module is ready
|
|
return false, fmt.Errorf("error decoding signature: %w", err)
|
|
}
|
|
|
|
currentTime := time.Now().Unix()
|
|
if createdTimestamp > currentTime || currentTime > expiredTimestamp {
|
|
// TODO: Return appropriate error code when Error Code Handling Module is ready
|
|
return false, fmt.Errorf("signature is expired or not yet valid")
|
|
}
|
|
|
|
createdTime := time.Unix(createdTimestamp, 0)
|
|
expiredTime := time.Unix(expiredTimestamp, 0)
|
|
|
|
signingString := hash(body, createdTime.Unix(), expiredTime.Unix())
|
|
|
|
decodedPublicKey, err := base64.StdEncoding.DecodeString(publicKeyBase64)
|
|
if err != nil {
|
|
// TODO: Return appropriate error code when Error Code Handling Module is ready
|
|
return false, fmt.Errorf("error decoding public key: %w", err)
|
|
}
|
|
|
|
if !ed25519.Verify(ed25519.PublicKey(decodedPublicKey), []byte(signingString), signatureBytes) {
|
|
// TODO: Return appropriate error code when Error Code Handling Module is ready
|
|
return false, fmt.Errorf("signature verification failed")
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// parseAuthHeader extracts signature values from the Authorization header.
|
|
func parseAuthHeader(header string) (int64, int64, string, error) {
|
|
header = strings.TrimPrefix(header, "Signature ")
|
|
|
|
parts := strings.Split(header, ",")
|
|
signatureMap := make(map[string]string)
|
|
|
|
for _, part := range parts {
|
|
keyValue := strings.SplitN(strings.TrimSpace(part), "=", 2)
|
|
if len(keyValue) == 2 {
|
|
key := strings.TrimSpace(keyValue[0])
|
|
value := strings.Trim(keyValue[1], "\"")
|
|
signatureMap[key] = value
|
|
}
|
|
}
|
|
|
|
createdTimestamp, err := strconv.ParseInt(signatureMap["created"], 10, 64)
|
|
if err != nil {
|
|
// TODO: Return appropriate error code when Error Code Handling Module is ready
|
|
return 0, 0, "", fmt.Errorf("invalid created timestamp: %w", err)
|
|
}
|
|
|
|
expiredTimestamp, err := strconv.ParseInt(signatureMap["expires"], 10, 64)
|
|
if err != nil {
|
|
// TODO: Return appropriate error code when Error Code Handling Module is ready
|
|
return 0, 0, "", fmt.Errorf("invalid expires timestamp: %w", err)
|
|
}
|
|
|
|
signature := signatureMap["signature"]
|
|
if signature == "" {
|
|
// TODO: Return appropriate error code when Error Code Handling Module is ready
|
|
return 0, 0, "", fmt.Errorf("signature missing in header")
|
|
}
|
|
|
|
return createdTimestamp, expiredTimestamp, signature, nil
|
|
}
|
|
|
|
// hash constructs a signing string for verification.
|
|
func hash(payload []byte, createdTimestamp, expiredTimestamp int64) string {
|
|
hasher, _ := blake2b.New512(nil)
|
|
hasher.Write(payload)
|
|
hashSum := hasher.Sum(nil)
|
|
digestB64 := base64.StdEncoding.EncodeToString(hashSum)
|
|
|
|
return fmt.Sprintf("(created): %d\n(expires): %d\ndigest: BLAKE-512=%s", createdTimestamp, expiredTimestamp, digestB64)
|
|
}
|
|
|
|
// Close releases resources (mock implementation returning nil).
|
|
func (v *Verifier) Close() error {
|
|
return nil
|
|
}
|