-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSignatureValidatorImpl.cs
92 lines (78 loc) · 3.3 KB
/
SignatureValidatorImpl.cs
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
/*
* Copyright (c) 2021 eBay Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Text;
using System.Text.Json;
using EbayEventNotificationSDK.Models;
using Org.BouncyCastle.Security;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
using EbayEventNotificationSDK.Exceptions;
namespace EbayEventNotificationSDK.Utils
{
public class SignatureValidatorImpl : ISignatureValidator
{
private readonly IPublicKeyCache publicKeyCache;
private readonly ILogger<SignatureValidatorImpl> logger;
public SignatureValidatorImpl(IPublicKeyCache publicKeyCache, ILogger<SignatureValidatorImpl> logger)
{
this.publicKeyCache = publicKeyCache;
this.logger = logger;
}
public Boolean validate(Message message, String signatureHeader)
{
try
{
String jsonString = DecodeBase64(signatureHeader);
XeBaySignature xeBaySignature = JsonSerializer.Deserialize<XeBaySignature>(jsonString);
var publicKey = publicKeyCache.getPublicKey(xeBaySignature.kid);
var plainTextBytes = Encoding.UTF8.GetBytes(getJSONString(message));
var pk = PublicKeyFactory.CreateKey(Convert.FromBase64String(GetRawKey(publicKey.key)));
var verifier = SignerUtilities.GetSigner(String.Format(Constants.Algorithm, publicKey.digest, publicKey.algorithm));
verifier.Init(false, pk);
verifier.BlockUpdate(plainTextBytes, 0, plainTextBytes.Length);
var result = verifier.VerifySignature(Convert.FromBase64String(xeBaySignature.signature));
if (result == false) logger.LogError("Signature mismatch for payload:" + getJSONString(message) + ": with signature:" + signatureHeader);
return result;
}
catch (Exception ex)
{
throw new SignatureValidationException(ex.Message);
}
}
private String getJSONString(Message message)
{
JsonSerializerOptions options = new JsonSerializerOptions();
options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
return JsonSerializer.Serialize(message, options);
}
private string GetRawKey(string key)
{
var regex = new Regex(Constants.KeyPattern);
var match = regex.Match(key);
if (match.Success)
{
return match.Groups[1].Value;
}
return key;
}
private string DecodeBase64(string value)
{
var valueBytes = System.Convert.FromBase64String(value);
return Encoding.UTF8.GetString(valueBytes);
}
}
}