ap2_mandate_verifier 0.1.0.pre.3
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +300 -0
- data/docs/SUPPORT_CONTRACT.md +284 -0
- data/lib/ap2_mandate_verifier/host_binding.rb +104 -0
- data/lib/ap2_mandate_verifier/input_validator.rb +104 -0
- data/lib/ap2_mandate_verifier/purchase_binding.rb +103 -0
- data/lib/ap2_mandate_verifier/research_result.rb +79 -0
- data/lib/ap2_mandate_verifier/result.rb +50 -0
- data/lib/ap2_mandate_verifier/root_disclosures.rb +100 -0
- data/lib/ap2_mandate_verifier/root_signature.rb +115 -0
- data/lib/ap2_mandate_verifier/scoped_constraints.rb +114 -0
- data/lib/ap2_mandate_verifier/trust_context.rb +123 -0
- data/lib/ap2_mandate_verifier.rb +128 -0
- metadata +123 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "ap2_mandate_verifier/result"
|
|
4
|
+
require_relative "ap2_mandate_verifier/input_validator"
|
|
5
|
+
require_relative "ap2_mandate_verifier/root_signature"
|
|
6
|
+
require_relative "ap2_mandate_verifier/root_disclosures"
|
|
7
|
+
require_relative "ap2_mandate_verifier/purchase_binding"
|
|
8
|
+
require_relative "ap2_mandate_verifier/scoped_constraints"
|
|
9
|
+
require_relative "ap2_mandate_verifier/trust_context"
|
|
10
|
+
require_relative "ap2_mandate_verifier/host_binding"
|
|
11
|
+
require_relative "ap2_mandate_verifier/research_result"
|
|
12
|
+
|
|
13
|
+
module AP2MandateVerifier
|
|
14
|
+
# Accepts original JSON bytes only. Syntax validity is not AP2 validity,
|
|
15
|
+
# authentication, disclosure completeness, or a Host authorization decision.
|
|
16
|
+
def self.verify(presentation_json:)
|
|
17
|
+
unavailable = InputValidator.check!(presentation_json)
|
|
18
|
+
return Result.new(status: :unavailable, code: unavailable) if unavailable
|
|
19
|
+
|
|
20
|
+
Result.new(status: :unverified, code: :verification_not_implemented)
|
|
21
|
+
rescue InputValidator::Invalid => error
|
|
22
|
+
Result.new(status: :rejected, code: error.code)
|
|
23
|
+
rescue LoadError
|
|
24
|
+
Result.new(status: :unavailable, code: :json_dependency_unavailable)
|
|
25
|
+
rescue StandardError
|
|
26
|
+
# Unexpected implementation/dependency failure is not proof of bad input.
|
|
27
|
+
# Do not expose parser messages, source text, or claim values.
|
|
28
|
+
Result.new(status: :unavailable, code: :input_check_unavailable)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# One original compact Root JWS only; no SD disclosure/authority validation.
|
|
32
|
+
# The caller must select this PUBLIC key independently of the token. This
|
|
33
|
+
# API does not establish the caller's key enrollment or Issuer provenance.
|
|
34
|
+
def self.verify_root_signature(root_jws:, trusted_issuer_public_key_pem:)
|
|
35
|
+
RootSignature.check!(root_jws, trusted_issuer_public_key_pem)
|
|
36
|
+
Result.new(status: :unverified, code: :root_signature_verified_only)
|
|
37
|
+
rescue InputValidator::Unavailable, RootSignature::Unavailable => error
|
|
38
|
+
Result.new(status: :unavailable, code: error.code)
|
|
39
|
+
rescue InputValidator::Invalid, RootSignature::Rejected => error
|
|
40
|
+
Result.new(status: :rejected, code: error.code)
|
|
41
|
+
rescue LoadError
|
|
42
|
+
Result.new(status: :unavailable, code: :signature_dependency_unavailable)
|
|
43
|
+
rescue StandardError
|
|
44
|
+
Result.new(status: :unavailable, code: :root_signature_check_unavailable)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Exact DC04 disclosure profile only. This grants no AP2/Host authority.
|
|
48
|
+
def self.verify_root_disclosures(presentation:, trusted_issuer_public_key_pem:)
|
|
49
|
+
RootDisclosures.check!(presentation, trusted_issuer_public_key_pem)
|
|
50
|
+
Result.new(status: :unverified, code: :root_disclosures_verified_only)
|
|
51
|
+
rescue InputValidator::Unavailable, RootSignature::Unavailable => error
|
|
52
|
+
Result.new(status: :unavailable, code: error.code)
|
|
53
|
+
rescue InputValidator::Invalid, RootSignature::Rejected => error
|
|
54
|
+
Result.new(status: :rejected, code: error.code)
|
|
55
|
+
rescue LoadError
|
|
56
|
+
Result.new(status: :unavailable, code: :disclosure_dependency_unavailable)
|
|
57
|
+
rescue StandardError
|
|
58
|
+
Result.new(status: :unavailable, code: :root_disclosure_check_unavailable)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.verify_purchase_binding(**inputs)
|
|
62
|
+
PurchaseBinding.check!(**inputs)
|
|
63
|
+
Result.new(status: :unverified, code: :purchase_binding_verified_only)
|
|
64
|
+
rescue InputValidator::Unavailable, RootSignature::Unavailable => error
|
|
65
|
+
Result.new(status: :unavailable, code: error.code)
|
|
66
|
+
rescue InputValidator::Invalid, RootSignature::Rejected => error
|
|
67
|
+
Result.new(status: :rejected, code: error.code)
|
|
68
|
+
rescue LoadError
|
|
69
|
+
Result.new(status: :unavailable, code: :purchase_dependency_unavailable)
|
|
70
|
+
rescue StandardError
|
|
71
|
+
Result.new(status: :unavailable, code: :purchase_check_unavailable)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.verify_scoped_constraints(**inputs)
|
|
75
|
+
ScopedConstraints.check!(**inputs)
|
|
76
|
+
Result.new(status: :unverified, code: :scoped_constraints_verified_only)
|
|
77
|
+
rescue InputValidator::Unavailable, RootSignature::Unavailable => error
|
|
78
|
+
Result.new(status: :unavailable, code: error.code)
|
|
79
|
+
rescue InputValidator::Invalid, RootSignature::Rejected => error
|
|
80
|
+
Result.new(status: :rejected, code: error.code)
|
|
81
|
+
rescue LoadError
|
|
82
|
+
Result.new(status: :unavailable, code: :constraint_dependency_unavailable)
|
|
83
|
+
rescue StandardError
|
|
84
|
+
Result.new(status: :unavailable, code: :constraint_check_unavailable)
|
|
85
|
+
end
|
|
86
|
+
# Both JSON inputs must come from authenticated Host state, independently of
|
|
87
|
+
# the presentation. Existing lower-level PEM APIs retain their old contract.
|
|
88
|
+
def self.verify_trusted_scoped_constraints(trust_json:, selection_json:, **inputs)
|
|
89
|
+
unless inputs.length == TrustContext::INPUTS.length && TrustContext::INPUTS.all? { |key| inputs.key?(key) }
|
|
90
|
+
return Result.new(status: :rejected, code: :invalid_trust_context)
|
|
91
|
+
end
|
|
92
|
+
# Snapshot Host context and signed wires before any trust/key processing;
|
|
93
|
+
# the identity comparison and downstream verifier must use identical bytes.
|
|
94
|
+
inputs = inputs.to_h do |key, value|
|
|
95
|
+
[key, %i[verified_at expected_total_minor].include?(key) ? value : InputValidator.snapshot!(value)]
|
|
96
|
+
end
|
|
97
|
+
keys = TrustContext.keys!(trust_json: trust_json, selection_json: selection_json,
|
|
98
|
+
verified_at: inputs[:verified_at], expected_merchant_id: inputs[:expected_merchant_id])
|
|
99
|
+
ScopedConstraints.check!(**inputs, **keys)
|
|
100
|
+
Result.new(status: :unverified, code: :scoped_constraints_verified_only)
|
|
101
|
+
rescue InputValidator::Unavailable, RootSignature::Unavailable => error
|
|
102
|
+
Result.new(status: :unavailable, code: error.code)
|
|
103
|
+
rescue InputValidator::Invalid, RootSignature::Rejected => error
|
|
104
|
+
Result.new(status: :rejected, code: error.code)
|
|
105
|
+
rescue LoadError
|
|
106
|
+
Result.new(status: :unavailable, code: :signature_dependency_unavailable)
|
|
107
|
+
rescue StandardError
|
|
108
|
+
Result.new(status: :unavailable, code: :trust_check_unavailable)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.verify_host_binding(**inputs)
|
|
112
|
+
HostBinding.check!(**inputs)
|
|
113
|
+
Result.new(status: :unverified, code: :host_binding_verified_only)
|
|
114
|
+
rescue InputValidator::Unavailable, RootSignature::Unavailable => error
|
|
115
|
+
Result.new(status: :unavailable, code: error.code)
|
|
116
|
+
rescue InputValidator::Invalid, RootSignature::Rejected => error
|
|
117
|
+
Result.new(status: :rejected, code: error.code)
|
|
118
|
+
rescue LoadError
|
|
119
|
+
Result.new(status: :unavailable, code: :signature_dependency_unavailable)
|
|
120
|
+
rescue StandardError
|
|
121
|
+
Result.new(status: :unavailable, code: :host_binding_check_unavailable)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Research Evidence only; success is not Host ALLOW or a payment permission.
|
|
125
|
+
# All older methods continue to return non-success Result values.
|
|
126
|
+
def self.verify_research(**inputs) = ResearchResult.verify(**inputs)
|
|
127
|
+
|
|
128
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ap2_mandate_verifier
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0.pre.3
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- AP2 Mandate Verifier contributors
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: json
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - '='
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 2.19.9
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - '='
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 2.19.9
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: jwt
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - '='
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 3.3.0
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - '='
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 3.3.0
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: base64
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - '='
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.3.0
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - '='
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.3.0
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: openssl
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - '='
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 4.0.2
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - '='
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 4.0.2
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: digest
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - '='
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 3.2.1
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - '='
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: 3.2.1
|
|
82
|
+
description: Stateless fixed-profile verification and immutable research Evidence;
|
|
83
|
+
not Host authorization or payment permission. Research-only prerelease candidate;
|
|
84
|
+
actual distribution requires separate Owner approval.
|
|
85
|
+
executables: []
|
|
86
|
+
extensions: []
|
|
87
|
+
extra_rdoc_files: []
|
|
88
|
+
files:
|
|
89
|
+
- LICENSE
|
|
90
|
+
- README.md
|
|
91
|
+
- docs/SUPPORT_CONTRACT.md
|
|
92
|
+
- lib/ap2_mandate_verifier.rb
|
|
93
|
+
- lib/ap2_mandate_verifier/host_binding.rb
|
|
94
|
+
- lib/ap2_mandate_verifier/input_validator.rb
|
|
95
|
+
- lib/ap2_mandate_verifier/purchase_binding.rb
|
|
96
|
+
- lib/ap2_mandate_verifier/research_result.rb
|
|
97
|
+
- lib/ap2_mandate_verifier/result.rb
|
|
98
|
+
- lib/ap2_mandate_verifier/root_disclosures.rb
|
|
99
|
+
- lib/ap2_mandate_verifier/root_signature.rb
|
|
100
|
+
- lib/ap2_mandate_verifier/scoped_constraints.rb
|
|
101
|
+
- lib/ap2_mandate_verifier/trust_context.rb
|
|
102
|
+
homepage: https://github.com/cuichangquan/ap2-mandate-verifier
|
|
103
|
+
licenses:
|
|
104
|
+
- MIT
|
|
105
|
+
metadata: {}
|
|
106
|
+
rdoc_options: []
|
|
107
|
+
require_paths:
|
|
108
|
+
- lib
|
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
110
|
+
requirements:
|
|
111
|
+
- - '='
|
|
112
|
+
- !ruby/object:Gem::Version
|
|
113
|
+
version: 4.0.9
|
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
|
+
requirements:
|
|
116
|
+
- - ">="
|
|
117
|
+
- !ruby/object:Gem::Version
|
|
118
|
+
version: '0'
|
|
119
|
+
requirements: []
|
|
120
|
+
rubygems_version: 4.0.20
|
|
121
|
+
specification_version: 4
|
|
122
|
+
summary: Fixed-profile AP2 research prerelease candidate
|
|
123
|
+
test_files: []
|