wave-dispatch 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/wave_dispatch.rb +34 -6
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4132ab0b5f81a3e912759da3d32a77629508687645eab9d475631a6f47a9e4b7
|
|
4
|
+
data.tar.gz: 66ae5e4b3895592957e4870ca7df3038ca2abe43020f7c9048380cb5466d31c9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c03bdcc61a39530fd52182943c741d5d05aff21078d251961599e8ddf18393a8c4280f28028a2f9eb78ac1736bc961304a93f0b5d1cc3e533f282952144ba934
|
|
7
|
+
data.tar.gz: 0eea51f1031d5ace0517fef4da3caaebcdbe4f21a0e7a75e585a03e0b1e37b747866aa973265e584c99f82ab75283c387471cef586ecf58c8f0a2e2360f6ff2a
|
data/lib/wave_dispatch.rb
CHANGED
|
@@ -7,7 +7,7 @@ require "uri"
|
|
|
7
7
|
require "openssl"
|
|
8
8
|
|
|
9
9
|
module WaveDispatch
|
|
10
|
-
VERSION = "0.6.
|
|
10
|
+
VERSION = "0.6.2"
|
|
11
11
|
|
|
12
12
|
# 0.5.1 — payment hook: a Proc called once with the 402 challenge body (Hash) that returns the
|
|
13
13
|
# headers (Hash[String => String]) to retry the request with. Pair with `Client.wallet_hook(provider:,
|
|
@@ -94,11 +94,14 @@ module WaveDispatch
|
|
|
94
94
|
accept = accepts.find { |a| a.is_a?(Hash) && a["protocol"] == provider.to_s } || accepts.first || {}
|
|
95
95
|
case provider
|
|
96
96
|
when :cdp
|
|
97
|
-
# CDP-JWT signing
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
# 0.6.2 — real CDP-JWT (ES256/P-256) signing via OpenSSL stdlib. creds: {api_key, api_secret (PEM EC),
|
|
98
|
+
# address?, network?}. The signed JWT is the cdp-payment header value; WAVE's CDP verifier validates
|
|
99
|
+
# the signature on its side. No optional dep needed — Ruby's stdlib OpenSSL handles everything.
|
|
100
|
+
raise "dispatch.wallet_hook(cdp): api_key required" unless creds[:api_key]
|
|
101
|
+
raise "dispatch.wallet_hook(cdp): api_secret required (PEM EC private key)" unless creds[:api_secret]
|
|
102
|
+
jwt = WaveDispatch.sign_cdp_jwt(creds, accept)
|
|
103
|
+
{ provider: "cdp", jwt: jwt, address: creds[:address],
|
|
104
|
+
network: creds[:network] || "base", accept: accept }.to_json
|
|
102
105
|
when :privy
|
|
103
106
|
%i[app_id app_secret wallet_id].each { |k| raise "dispatch.wallet_hook(privy): #{k} required" unless creds[k] }
|
|
104
107
|
basic = Base64.strict_encode64("#{creds[:app_id]}:#{creds[:app_secret]}")
|
|
@@ -127,4 +130,29 @@ module WaveDispatch
|
|
|
127
130
|
raise "dispatch.wallet_sign: unsupported provider #{provider.inspect}"
|
|
128
131
|
end
|
|
129
132
|
end
|
|
133
|
+
|
|
134
|
+
# 0.6.2 — CDP-JWT (ES256/P-256) signing via OpenSSL stdlib. Header:
|
|
135
|
+
# {alg:'ES256', kid:<api_key>, typ:'JWT', nonce:<rand-hex16>}. Payload: {sub:<api_key>, iss:'cdp',
|
|
136
|
+
# nbf:<now>, exp:<now+120>, uri:'POST dispatch.wave.online<resource>', claim:<accept>}.
|
|
137
|
+
# ECDSA signs the base64url(header).base64url(payload) input; the DER signature is unpacked to raw
|
|
138
|
+
# 32+32 r||s (IEEE P-1363), which is exactly what JWS ES256 expects.
|
|
139
|
+
def self.sign_cdp_jwt(creds, accept)
|
|
140
|
+
require "openssl"
|
|
141
|
+
require "securerandom"
|
|
142
|
+
nonce = SecureRandom.hex(16)
|
|
143
|
+
now = Time.now.to_i
|
|
144
|
+
uri = "POST dispatch.wave.online#{(accept || {})["resource"] || "/"}"
|
|
145
|
+
header = { alg: "ES256", kid: creds[:api_key], typ: "JWT", nonce: nonce }
|
|
146
|
+
payload = { sub: creds[:api_key], iss: "cdp", nbf: now, exp: now + 120, uri: uri, claim: accept }
|
|
147
|
+
b64url = ->(s) { Base64.urlsafe_encode64(s).gsub("=", "") }
|
|
148
|
+
to_sign = b64url.call(header.to_json) + "." + b64url.call(payload.to_json)
|
|
149
|
+
key = OpenSSL::PKey.read(creds[:api_secret])
|
|
150
|
+
raise "dispatch.wallet_hook(cdp): api_secret must be an EC P-256 private key" unless key.is_a?(OpenSSL::PKey::EC)
|
|
151
|
+
der_sig = key.sign(OpenSSL::Digest.new("SHA256"), to_sign)
|
|
152
|
+
# DER → raw r||s. OpenSSL ASN1 parses the SEQUENCE into [r, s] big-integers.
|
|
153
|
+
asn1 = OpenSSL::ASN1.decode(der_sig)
|
|
154
|
+
r = asn1.value[0].value.to_s(2).rjust(32, "\x00".b)
|
|
155
|
+
s = asn1.value[1].value.to_s(2).rjust(32, "\x00".b)
|
|
156
|
+
to_sign + "." + b64url.call(r + s)
|
|
157
|
+
end
|
|
130
158
|
end
|