mirror of
https://github.com/penpot/penpot.git
synced 2026-08-07 13:29:07 +00:00
🐛 Fix SNS signature verification field sets per AWS spec
Address critical code review findings: - Remove 'Signature' field from string-to-sign (it's the output, not input) - Differentiate V1 vs V2 field sets per AWS SNS documentation: - V1 Notification: Message, MessageId, Subject, Timestamp, TopicArn, Type - V1 SubscriptionConfirmation: adds Token, SubscribeURL (excludes SigningCertURL, SignatureVersion) - V2 Notification/Subscription: all fields except Signature - Add 'Token' field to SubscriptionConfirmation (required by AWS spec) - Add AWS documentation URL comments for future reference - Improve error handling in fetch-certificate and verify-signature - Add end-to-end signature verification tests with real key pairs - Add test resources (certificate and private key) for signature tests See: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html Closes #11092 AI-assisted-by: qwen3.7-plus
This commit is contained in:
parent
2101d657e5
commit
a4b9ccee8b
@ -77,7 +77,7 @@
|
||||
org.clojure/data.csv {:mvn/version "1.1.1"}
|
||||
com.clojure-goes-fast/clj-async-profiler {:mvn/version "2.0.0-beta1"}
|
||||
mockery/mockery {:mvn/version "0.1.4"}}
|
||||
:extra-paths ["test" "dev"]}
|
||||
:extra-paths ["test" "test/resources" "dev"]}
|
||||
|
||||
:build
|
||||
{:extra-deps
|
||||
|
||||
@ -35,7 +35,8 @@
|
||||
|
||||
(defn- valid-sns-url?
|
||||
"Validates that a URL originates from an SNS endpoint.
|
||||
Only accepts sns.<region>.amazonaws.com hosts."
|
||||
Only accepts sns.<region>.amazonaws.com hosts.
|
||||
See: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html"
|
||||
[url]
|
||||
(when (string? url)
|
||||
(try
|
||||
@ -49,21 +50,52 @@
|
||||
(catch Exception _
|
||||
false))))
|
||||
|
||||
(def ^:private notification-fields
|
||||
["Message" "MessageId" "Subject" "Timestamp"
|
||||
"TopicArn" "Type" "SigningCertURL" "SignatureVersion" "Signature"])
|
||||
;; AWS SNS Signature Verification Field Sets
|
||||
;; See: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html
|
||||
;;
|
||||
;; Signature Version 1 signs only specific fields (excludes SigningCertURL, SignatureVersion, Signature)
|
||||
;; Signature Version 2 signs all fields except Signature
|
||||
;;
|
||||
;; IMPORTANT: The "Signature" field is NEVER part of the string-to-sign (it's the output, not input)
|
||||
|
||||
(def ^:private subscription-fields
|
||||
["Message" "MessageId" "SubscribeURL" "Timestamp"
|
||||
"TopicArn" "Type" "SigningCertURL" "SignatureVersion" "Signature"])
|
||||
;; V1 Notification: Message, MessageId, Subject (if present), Timestamp, TopicArn, Type
|
||||
(def ^:private v1-notification-fields
|
||||
["Message" "MessageId" "Subject" "Timestamp" "TopicArn" "Type"])
|
||||
|
||||
;; V1 SubscriptionConfirmation: Message, MessageId, SubscribeURL, Timestamp, Token, TopicArn, Type
|
||||
(def ^:private v1-subscription-fields
|
||||
["Message" "MessageId" "SubscribeURL" "Timestamp" "Token" "TopicArn" "Type"])
|
||||
|
||||
;; V2 Notification: All fields except Signature
|
||||
(def ^:private v2-notification-fields
|
||||
["Message" "MessageId" "Subject" "Timestamp" "TopicArn" "Type"
|
||||
"SigningCertURL" "SignatureVersion"])
|
||||
|
||||
;; V2 SubscriptionConfirmation: All fields except Signature (includes Token)
|
||||
(def ^:private v2-subscription-fields
|
||||
["Message" "MessageId" "SubscribeURL" "Timestamp" "Token" "TopicArn" "Type"
|
||||
"SigningCertURL" "SignatureVersion"])
|
||||
|
||||
(defn- build-string-to-sign
|
||||
"Builds the string-to-sign for AWS SNS signature verification.
|
||||
See: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html"
|
||||
[body]
|
||||
(let [fields (if (= "SubscriptionConfirmation" (get body "Type"))
|
||||
subscription-fields
|
||||
notification-fields)]
|
||||
(let [sig-version (get body "SignatureVersion")
|
||||
msg-type (get body "Type")
|
||||
fields (cond
|
||||
(= "1" sig-version)
|
||||
(if (= "SubscriptionConfirmation" msg-type)
|
||||
v1-subscription-fields
|
||||
v1-notification-fields)
|
||||
|
||||
(= "2" sig-version)
|
||||
(if (= "SubscriptionConfirmation" msg-type)
|
||||
v2-subscription-fields
|
||||
v2-notification-fields)
|
||||
|
||||
:else
|
||||
(throw (ex-info "Unsupported SNS signature version"
|
||||
{:version sig-version})))]
|
||||
(->> fields
|
||||
(filter #(contains? body %))
|
||||
(map #(str % "\n" (get body %) "\n"))
|
||||
@ -71,36 +103,52 @@
|
||||
|
||||
(defn- fetch-certificate
|
||||
"Fetches the X.509 certificate from the given URL.
|
||||
Returns an InputStream that must be closed by the caller."
|
||||
Returns an InputStream that must be closed by the caller.
|
||||
See: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html"
|
||||
[cfg cert-url]
|
||||
(let [response (http/req cfg {:uri cert-url :method :get :timeout 10000}
|
||||
{:sync? true :response-type :input-stream})]
|
||||
(when (= 200 (:status response))
|
||||
(:body response))))
|
||||
(when-not (= 200 (:status response))
|
||||
(l/wrn :hint "failed to fetch SNS signing certificate"
|
||||
:action "sns-cert-fetch-failed"
|
||||
:status (:status response)
|
||||
:cert-url cert-url)
|
||||
(ex/raise :type :internal :code :cert-fetch-failed))
|
||||
(:body response)))
|
||||
|
||||
(defn- verify-signature
|
||||
"Verifies the RSA signature of the message."
|
||||
"Verifies the RSA signature of the message.
|
||||
See: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html"
|
||||
[cfg body]
|
||||
(let [cert-url (get body "SigningCertURL")
|
||||
signature (get body "Signature")
|
||||
sig-version (get body "SignatureVersion")
|
||||
string-sign (build-string-to-sign body)
|
||||
algorithm (case sig-version
|
||||
"1" "SHA1withRSA"
|
||||
"2" "SHA256withRSA"
|
||||
nil)]
|
||||
(when-not algorithm
|
||||
(throw (ex-info "Unsupported SNS signature version"
|
||||
{:version sig-version})))
|
||||
{:type :validation :version sig-version})))
|
||||
(when (and cert-url signature)
|
||||
(try
|
||||
(with-open [cert-stream (fetch-certificate cfg cert-url)]
|
||||
(let [cf (CertificateFactory/getInstance "X.509")
|
||||
cert (.generateCertificate cf cert-stream)
|
||||
sig (Signature/getInstance algorithm)]
|
||||
(.initVerify sig (.getPublicKey cert))
|
||||
(.update sig (.getBytes string-sign java.nio.charset.StandardCharsets/UTF_8))
|
||||
(.verify sig (.decode (Base64/getDecoder) signature))))
|
||||
(let [string-sign (build-string-to-sign body)]
|
||||
(with-open [cert-stream (fetch-certificate cfg cert-url)]
|
||||
(let [cf (CertificateFactory/getInstance "X.509")
|
||||
cert (.generateCertificate cf cert-stream)
|
||||
sig (Signature/getInstance algorithm)]
|
||||
(.initVerify sig (.getPublicKey cert))
|
||||
(.update sig (.getBytes string-sign java.nio.charset.StandardCharsets/UTF_8))
|
||||
(.verify sig (.decode (Base64/getDecoder) signature)))))
|
||||
(catch clojure.lang.ExceptionInfo e
|
||||
(let [data (ex-data e)]
|
||||
(if (= :validation (:type data))
|
||||
(throw e)
|
||||
(do
|
||||
(l/wrn :hint "SNS signature verification exception"
|
||||
:action "sns-signature-verification-exception"
|
||||
:cause e)
|
||||
false))))
|
||||
(catch Exception e
|
||||
(l/wrn :hint "SNS signature verification exception"
|
||||
:action "sns-signature-verification-exception"
|
||||
@ -109,7 +157,8 @@
|
||||
|
||||
(defn- verify-sns-message!
|
||||
"Verifies the AWS SNS message signature and URL validity.
|
||||
Throws if verification fails."
|
||||
Throws if verification fails.
|
||||
See: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html"
|
||||
[cfg body]
|
||||
(let [cert-url (get body "SigningCertURL")
|
||||
subscribe-url (get body "SubscribeURL")
|
||||
|
||||
@ -308,66 +308,130 @@
|
||||
(t/is (true? (#'awsns/valid-sns-url? "https://sns.us-east-1.amazonaws.com/cert.pem")))
|
||||
(t/is (true? (#'awsns/valid-sns-url? "https://sns.ap-southeast-1.amazonaws.com/cert.pem"))))
|
||||
|
||||
(t/deftest test-verify-signature-version-1
|
||||
(let [keypair (java.security.KeyPairGenerator/getInstance "RSA")
|
||||
_ (.initialize keypair 2048)
|
||||
kp (.generateKeyPair keypair)
|
||||
private-key (.getPrivate kp)
|
||||
public-key (.getPublic kp)
|
||||
;; Helper to load test certificate and private key from resources
|
||||
;; See: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html
|
||||
(defn- load-test-cert-and-key
|
||||
"Loads the test certificate and private key from test resources."
|
||||
[]
|
||||
(let [cert-pem (slurp (clojure.java.io/resource "sns-test-cert.pem"))
|
||||
key-pem (slurp (clojure.java.io/resource "sns-test-key.pem"))
|
||||
;; Parse certificate
|
||||
cert-bytes (.getBytes (-> cert-pem
|
||||
(clojure.string/replace "-----BEGIN CERTIFICATE-----" "")
|
||||
(clojure.string/replace "-----END CERTIFICATE-----" "")
|
||||
(clojure.string/replace #"\s+" ""))
|
||||
java.nio.charset.StandardCharsets/UTF_8)
|
||||
cert-input (java.io.ByteArrayInputStream. (.decode (java.util.Base64/getDecoder) cert-bytes))
|
||||
cf (java.security.cert.CertificateFactory/getInstance "X.509")
|
||||
cert (.generateCertificate cf cert-input)
|
||||
;; Parse private key
|
||||
key-bytes (.getBytes (-> key-pem
|
||||
(clojure.string/replace "-----BEGIN PRIVATE KEY-----" "")
|
||||
(clojure.string/replace "-----END PRIVATE KEY-----" "")
|
||||
(clojure.string/replace #"\s+" ""))
|
||||
java.nio.charset.StandardCharsets/UTF_8)
|
||||
key-spec (java.security.spec.PKCS8EncodedKeySpec. (.decode (java.util.Base64/getDecoder) key-bytes))
|
||||
kf (java.security.KeyFactory/getInstance "RSA")
|
||||
private-key (.generatePrivate kf key-spec)]
|
||||
{:cert cert
|
||||
:cert-bytes (.getEncoded cert)
|
||||
:private-key private-key
|
||||
:public-key (.getPublicKey cert)}))
|
||||
|
||||
;; Create a simple message
|
||||
msg {"Type" "Notification"
|
||||
"MessageId" "test-msg-1"
|
||||
"TopicArn" "arn:aws:sns:us-east-1:123:topic"
|
||||
"Message" "test message"
|
||||
"Timestamp" "2021-02-04T14:41:37.020Z"
|
||||
"SigningCertURL" "https://sns.us-east-1.amazonaws.com/cert.pem"
|
||||
"SignatureVersion" "1"}
|
||||
(t/deftest test-verify-signature-end-to-end-v1
|
||||
(let [{:keys [cert-bytes private-key]} (load-test-cert-and-key)
|
||||
|
||||
msg {"Type" "Notification"
|
||||
"MessageId" "test-msg-1"
|
||||
"TopicArn" "arn:aws:sns:us-east-1:123:topic"
|
||||
"Message" "test message"
|
||||
"Timestamp" "2021-02-04T14:41:37.020Z"
|
||||
"SigningCertURL" "https://sns.us-east-1.amazonaws.com/cert.pem"
|
||||
"SignatureVersion" "1"}
|
||||
|
||||
;; Build string to sign
|
||||
string-to-sign (#'awsns/build-string-to-sign msg)
|
||||
|
||||
;; Sign with SHA1
|
||||
sig (java.security.Signature/getInstance "SHA1withRSA")
|
||||
_ (.initSign sig private-key)
|
||||
_ (.update sig (.getBytes string-to-sign java.nio.charset.StandardCharsets/UTF_8))
|
||||
signature (.encodeToString (java.util.Base64/getEncoder) (.sign sig))
|
||||
|
||||
sig (java.security.Signature/getInstance "SHA1withRSA")
|
||||
_ (.initSign sig private-key)
|
||||
_ (.update sig (.getBytes string-to-sign java.nio.charset.StandardCharsets/UTF_8))
|
||||
signature (.encodeToString (java.util.Base64/getEncoder) (.sign sig))
|
||||
msg-with-sig (assoc msg "Signature" signature)]
|
||||
|
||||
;; Test that signature verification logic would work
|
||||
(t/is (string? string-to-sign))
|
||||
(t/is (string? signature))))
|
||||
(with-redefs [awsns/fetch-certificate (fn [_ _]
|
||||
(java.io.ByteArrayInputStream. cert-bytes))]
|
||||
(t/is (true? (#'awsns/verify-signature {} msg-with-sig))))))
|
||||
|
||||
(t/deftest test-verify-signature-version-2
|
||||
(let [keypair (java.security.KeyPairGenerator/getInstance "RSA")
|
||||
_ (.initialize keypair 2048)
|
||||
kp (.generateKeyPair keypair)
|
||||
private-key (.getPrivate kp)
|
||||
(t/deftest test-verify-signature-end-to-end-v2
|
||||
(let [{:keys [cert-bytes private-key]} (load-test-cert-and-key)
|
||||
|
||||
;; Create a simple message
|
||||
msg {"Type" "Notification"
|
||||
"MessageId" "test-msg-2"
|
||||
"TopicArn" "arn:aws:sns:us-east-1:123:topic"
|
||||
"Message" "test message"
|
||||
"Timestamp" "2021-02-04T14:41:37.020Z"
|
||||
"SigningCertURL" "https://sns.us-east-1.amazonaws.com/cert.pem"
|
||||
"SignatureVersion" "2"}
|
||||
msg {"Type" "Notification"
|
||||
"MessageId" "test-msg-2"
|
||||
"TopicArn" "arn:aws:sns:us-east-1:123:topic"
|
||||
"Message" "test message"
|
||||
"Timestamp" "2021-02-04T14:41:37.020Z"
|
||||
"SigningCertURL" "https://sns.us-east-1.amazonaws.com/cert.pem"
|
||||
"SignatureVersion" "2"}
|
||||
|
||||
;; Build string to sign
|
||||
string-to-sign (#'awsns/build-string-to-sign msg)
|
||||
|
||||
;; Sign with SHA256
|
||||
sig (java.security.Signature/getInstance "SHA256withRSA")
|
||||
_ (.initSign sig private-key)
|
||||
_ (.update sig (.getBytes string-to-sign java.nio.charset.StandardCharsets/UTF_8))
|
||||
signature (.encodeToString (java.util.Base64/getEncoder) (.sign sig))
|
||||
|
||||
sig (java.security.Signature/getInstance "SHA256withRSA")
|
||||
_ (.initSign sig private-key)
|
||||
_ (.update sig (.getBytes string-to-sign java.nio.charset.StandardCharsets/UTF_8))
|
||||
signature (.encodeToString (java.util.Base64/getEncoder) (.sign sig))
|
||||
msg-with-sig (assoc msg "Signature" signature)]
|
||||
|
||||
;; Test that signature verification logic would work
|
||||
(t/is (string? string-to-sign))
|
||||
(t/is (string? signature))))
|
||||
(with-redefs [awsns/fetch-certificate (fn [_ _]
|
||||
(java.io.ByteArrayInputStream. cert-bytes))]
|
||||
(t/is (true? (#'awsns/verify-signature {} msg-with-sig))))))
|
||||
|
||||
(t/deftest test-verify-signature-end-to-end-subscription-confirmation
|
||||
(let [{:keys [cert-bytes private-key]} (load-test-cert-and-key)
|
||||
|
||||
msg {"Type" "SubscriptionConfirmation"
|
||||
"MessageId" "test-msg-3"
|
||||
"TopicArn" "arn:aws:sns:us-east-1:123:topic"
|
||||
"Message" "You have chosen to subscribe"
|
||||
"Timestamp" "2021-02-04T14:41:37.020Z"
|
||||
"Token" "test-token-123"
|
||||
"SubscribeURL" "https://sns.us-east-1.amazonaws.com/confirm"
|
||||
"SigningCertURL" "https://sns.us-east-1.amazonaws.com/cert.pem"
|
||||
"SignatureVersion" "1"}
|
||||
|
||||
string-to-sign (#'awsns/build-string-to-sign msg)
|
||||
sig (java.security.Signature/getInstance "SHA1withRSA")
|
||||
_ (.initSign sig private-key)
|
||||
_ (.update sig (.getBytes string-to-sign java.nio.charset.StandardCharsets/UTF_8))
|
||||
signature (.encodeToString (java.util.Base64/getEncoder) (.sign sig))
|
||||
msg-with-sig (assoc msg "Signature" signature)]
|
||||
|
||||
(with-redefs [awsns/fetch-certificate (fn [_ _]
|
||||
(java.io.ByteArrayInputStream. cert-bytes))]
|
||||
(t/is (true? (#'awsns/verify-signature {} msg-with-sig))))))
|
||||
|
||||
(t/deftest test-verify-signature-rejects-wrong-key
|
||||
(let [{:keys [cert-bytes]} (load-test-cert-and-key)
|
||||
;; Generate a different keypair for signing
|
||||
keypair-gen (java.security.KeyPairGenerator/getInstance "RSA")
|
||||
_ (.initialize keypair-gen 2048)
|
||||
kp (.generateKeyPair keypair-gen)
|
||||
wrong-private-key (.getPrivate kp)
|
||||
|
||||
msg {"Type" "Notification"
|
||||
"MessageId" "test-msg-4"
|
||||
"TopicArn" "arn:aws:sns:us-east-1:123:topic"
|
||||
"Message" "test message"
|
||||
"Timestamp" "2021-02-04T14:41:37.020Z"
|
||||
"SigningCertURL" "https://sns.us-east-1.amazonaws.com/cert.pem"
|
||||
"SignatureVersion" "1"}
|
||||
|
||||
string-to-sign (#'awsns/build-string-to-sign msg)
|
||||
sig (java.security.Signature/getInstance "SHA1withRSA")
|
||||
_ (.initSign sig wrong-private-key)
|
||||
_ (.update sig (.getBytes string-to-sign java.nio.charset.StandardCharsets/UTF_8))
|
||||
signature (.encodeToString (java.util.Base64/getEncoder) (.sign sig))
|
||||
msg-with-sig (assoc msg "Signature" signature)]
|
||||
|
||||
(with-redefs [awsns/fetch-certificate (fn [_ _]
|
||||
(java.io.ByteArrayInputStream. cert-bytes))]
|
||||
(t/is (false? (#'awsns/verify-signature {} msg-with-sig))))))
|
||||
|
||||
(t/deftest test-verify-signature-rejects-unsupported-version
|
||||
(let [msg {"Type" "Notification"
|
||||
@ -379,11 +443,10 @@
|
||||
"SignatureVersion" "3"
|
||||
"Signature" "fake=="}]
|
||||
|
||||
;; Should throw exception for unsupported version
|
||||
(t/is (thrown? clojure.lang.ExceptionInfo
|
||||
(#'awsns/verify-signature {} msg)))))
|
||||
|
||||
(t/deftest test-build-string-to-sign-notification
|
||||
(t/deftest test-build-string-to-sign-v1-notification
|
||||
(let [msg {"Type" "Notification"
|
||||
"MessageId" "msg-123"
|
||||
"TopicArn" "arn:aws:sns:eu-central-1:123:topic"
|
||||
@ -399,8 +462,30 @@
|
||||
(t/is (.contains result "TopicArn"))
|
||||
(t/is (.contains result "Message"))
|
||||
(t/is (.contains result "Timestamp"))
|
||||
;; V1 does NOT include SigningCertURL, SignatureVersion, or Signature
|
||||
(t/is (not (.contains result "SigningCertURL")))
|
||||
(t/is (not (.contains result "SignatureVersion")))
|
||||
(t/is (not (.contains result "Signature")))))
|
||||
|
||||
(t/deftest test-build-string-to-sign-v2-notification
|
||||
(let [msg {"Type" "Notification"
|
||||
"MessageId" "msg-123"
|
||||
"TopicArn" "arn:aws:sns:eu-central-1:123:topic"
|
||||
"Message" "{\"notificationType\":\"Bounce\"}"
|
||||
"Timestamp" "2021-02-04T14:41:37.020Z"
|
||||
"SigningCertURL" "https://sns.eu-central-1.amazonaws.com/cert.pem"
|
||||
"SignatureVersion" "2"
|
||||
"Signature" "abc123=="}
|
||||
result (#'awsns/build-string-to-sign msg)]
|
||||
(t/is (string? result))
|
||||
(t/is (.contains result "MessageId"))
|
||||
(t/is (.contains result "TopicArn"))
|
||||
;; V2 includes SigningCertURL and SignatureVersion but NOT Signature
|
||||
(t/is (.contains result "SigningCertURL"))
|
||||
(t/is (.contains result "SignatureVersion"))))
|
||||
(t/is (.contains result "SignatureVersion"))
|
||||
;; Check that "Signature\n" (the field name) is NOT in the result
|
||||
;; Note: "SignatureVersion" contains "Signature" as substring, so we check for the exact field pattern
|
||||
(t/is (not (.contains result "Signature\n")))))
|
||||
|
||||
(t/deftest test-build-string-to-sign-subscription-confirmation
|
||||
(let [msg {"Type" "SubscriptionConfirmation"
|
||||
@ -408,6 +493,7 @@
|
||||
"TopicArn" "arn:aws:sns:eu-central-1:123:topic"
|
||||
"Message" "You have chosen to subscribe"
|
||||
"Timestamp" "2021-02-04T14:41:37.020Z"
|
||||
"Token" "test-token-123"
|
||||
"SigningCertURL" "https://sns.eu-central-1.amazonaws.com/cert.pem"
|
||||
"SignatureVersion" "1"
|
||||
"Signature" "xyz789=="
|
||||
@ -415,7 +501,10 @@
|
||||
result (#'awsns/build-string-to-sign msg)]
|
||||
(t/is (string? result))
|
||||
(t/is (.contains result "SubscribeURL"))
|
||||
(t/is (.contains result "https://sns.eu-central-1.amazonaws.com/confirm"))))
|
||||
(t/is (.contains result "https://sns.eu-central-1.amazonaws.com/confirm"))
|
||||
;; Token must be included for SubscriptionConfirmation
|
||||
(t/is (.contains result "Token"))
|
||||
(t/is (.contains result "test-token-123"))))
|
||||
|
||||
(t/deftest test-handle-request-returns-4xx-for-invalid-signature
|
||||
(let [body (j/write-str
|
||||
|
||||
19
backend/test/resources/sns-test-cert.pem
Normal file
19
backend/test/resources/sns-test-cert.pem
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDGDCCAgCgAwIBAgIJAMp8qfcfOi+AMA0GCSqGSIb3DQEBDAUAMDoxCzAJBgNV
|
||||
BAYTAlVTMQ0wCwYDVQQHEwRUZXN0MQ0wCwYDVQQKEwRUZXN0MQ0wCwYDVQQDEwRU
|
||||
ZXN0MB4XDTI2MDgwNTE1NTQxN1oXDTI3MDgwNTE1NTQxN1owOjELMAkGA1UEBhMC
|
||||
VVMxDTALBgNVBAcTBFRlc3QxDTALBgNVBAoTBFRlc3QxDTALBgNVBAMTBFRlc3Qw
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDj18ep0Pm5Y8VdXOSH9kXv
|
||||
7RWzmxfNvN/zD1Fp2scADGBXnuVUhHYoR09Pe8U26X2gmDRg+JS7h6XXcGaWGUyh
|
||||
28HISH3J0XrnKQmDKO77kxWFOAeu5apP2NVv1Nndbv+VqQczZqNZ6Kq9juflHjfK
|
||||
hnnYiQqKZZ118IMCnu0uX26ShTwZJe7rAtO4MB4UNnfmAeRdrBOdI+1fp7QItYRc
|
||||
2ppK3pXo2MAh8WhFeUy2UrlW6w1FpRjG/8nMmr14mD/dP9aWW85vcht5sA19bU3I
|
||||
sf8ZOxOO9SGAk8Tg5Ey8aCdL5BU05OF8PNClOuqhHdGKShul3n2Pgojb2yGBHTYB
|
||||
AgMBAAGjITAfMB0GA1UdDgQWBBTQbRwLjgbx/S7j1S/QFNB5HakDEjANBgkqhkiG
|
||||
9w0BAQwFAAOCAQEAklxu68LkEdTFthA/ASyzm7KNxiWw+k+9IaEcViuwVa3XR2Ly
|
||||
cO3L00NznsctwtcbevIT6ZlaK454snnpc5qZWHZSTYjQP34svT+XUZkgT29JdiYe
|
||||
r5so+cUdorJyngMAen/tzpAHXV2l9SbRsi5+fRkR8DjPv9Ctz+kmh/Oy5fF3x/nu
|
||||
AVZiwO8Oq4M3r+ElEfFed+9MkIQ6OZ3+ezgRhJYlXzVzii1OYQYpndocGNB+Jgwy
|
||||
1FqzP1/02dzT6Oz95Md3B9fxj0OSCpCCBMo3ihkOKuNixaqyQ2+n/06Y+qpvnfuM
|
||||
YrXnhbdpH7hsJM0/xNjWJMQlP04+zr1CQ9V9tg==
|
||||
-----END CERTIFICATE-----
|
||||
28
backend/test/resources/sns-test-key.pem
Normal file
28
backend/test/resources/sns-test-key.pem
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDj18ep0Pm5Y8Vd
|
||||
XOSH9kXv7RWzmxfNvN/zD1Fp2scADGBXnuVUhHYoR09Pe8U26X2gmDRg+JS7h6XX
|
||||
cGaWGUyh28HISH3J0XrnKQmDKO77kxWFOAeu5apP2NVv1Nndbv+VqQczZqNZ6Kq9
|
||||
juflHjfKhnnYiQqKZZ118IMCnu0uX26ShTwZJe7rAtO4MB4UNnfmAeRdrBOdI+1f
|
||||
p7QItYRc2ppK3pXo2MAh8WhFeUy2UrlW6w1FpRjG/8nMmr14mD/dP9aWW85vcht5
|
||||
sA19bU3Isf8ZOxOO9SGAk8Tg5Ey8aCdL5BU05OF8PNClOuqhHdGKShul3n2Pgojb
|
||||
2yGBHTYBAgMBAAECggEAIPku65wTL+nI+9iAOE8DUxQoIlyNJtixPl9WpG+lghPI
|
||||
c5XK0Z7z7KNZToL2iRpkdHPijLAc8kDQ1uts5UcXCIuhsUcQcT8wPrj5J/KqF11z
|
||||
bVqs/fo92h1i0jLnLr0sHvAd2yn89PuPjixa0hU79MLeamB21o2bKqDajOwMHjwq
|
||||
bAFUED3rmQe0nLv1pJbCIUUqd4ZElx+/XV+Y0c329zfA0WzjJI2EkHCnsS4tQn50
|
||||
KX77Mzcbm9ujVQf2xsr5pnRscsCk2LrzXmAW4nOw5jpeWxxudvVTzARhpv46mj0j
|
||||
MN0EN00YSw9FAHXBwDrjzS6cvvkchmBTJCUpKcoEWQKBgQDmO23YlsHrtnpWZRKf
|
||||
BTu/uIObLHXgNt1yXby0mFk2BSe6L6yJDxalJQ1jxdyay73+LLBUdJwfg2K/jRdw
|
||||
PFDdOvSRpb42LxTJ0TQxNaXsr91FDmbkjj0rFk1ygZKd/79HZq7xKWsfHsyTfUI7
|
||||
wgYz9QaapYYM1t1+diXlWxupJQKBgQD9V+T0EsuOTof8goKcBNw6C8zPnif8mKwy
|
||||
qtFWVySWpcreq74Q9+qyhMzNKDQ2flb1Akc6J3CSSvZBR21IKuqk9Cgu3qMH5CrX
|
||||
pe8smw8LpPaO5adnHvRgPTih7tJ0u7jUErWhmavkqroEq6DmvngmQ/6w9nhwTaC4
|
||||
tWfJzPvIrQKBgQDA19qEZpJ7y1bhcruMMyf+yKCDo1QAwDPwjY94fXuMAflqvG/6
|
||||
RYckQMrcXWkQx8OWWPxBYYM76iMWaynMutjI1Y7xSDDw1bLF8NOUvGkEvbHLG+sX
|
||||
WgTmSEIKvXl/mi4vslSqb5TodjXI/Ew0HapwbrZfZnHH41mXiYLof83FeQKBgQDK
|
||||
91T1ee1c6GuoEINFLdumIXgHyeStST+EJDgsXQpyKwd6F8vhWk3MkfpmTtRt6BAQ
|
||||
oK+h1qEogygBKpFR5Rgx6W4cBsBEfTcZp9YTPXLzWEk0OKdCRZlxVPr/OQ+g+Bhe
|
||||
x1J+0lfVjjYTsdDprCUkOwtciUn6ZybhdGxfT3tUzQKBgQC2BxPNlzPJvRkLvfMJ
|
||||
fJXfM9g96Uy7to7a7+LcLB2+OEAt/5kQAMg6ishwwoNvxVMtdy5uLEYNpq74lnQ2
|
||||
bCVc7qc834edVMykhjlK5CLu0GiK2NM4aQavBNRGBoLF7I1Ih+tcToZFUC6W8YEU
|
||||
djPrILOfRncjBj+epHXo92Z0iA==
|
||||
-----END PRIVATE KEY-----
|
||||
Loading…
x
Reference in New Issue
Block a user