virgil-sdk 4.2.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/.DS_Store +0 -0
- data/.gitignore +15 -0
- data/Gemfile +4 -0
- data/README.md +134 -0
- data/Rakefile +9 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/dockefiles/Dockerfile-200 +25 -0
- data/dockefiles/Dockerfile-2110 +36 -0
- data/dockefiles/Dockerfile-220 +26 -0
- data/dockefiles/Dockerfile-226 +25 -0
- data/dockefiles/Dockerfile-233 +25 -0
- data/dockefiles/Dockerfile-240 +26 -0
- data/docker-compose.yml +107 -0
- data/lib/virgil/sdk.rb +10 -0
- data/lib/virgil/sdk/client.rb +47 -0
- data/lib/virgil/sdk/client/card.rb +142 -0
- data/lib/virgil/sdk/client/card_validator.rb +104 -0
- data/lib/virgil/sdk/client/http.rb +45 -0
- data/lib/virgil/sdk/client/http/base_connection.rb +112 -0
- data/lib/virgil/sdk/client/http/cards_service_connection.rb +113 -0
- data/lib/virgil/sdk/client/http/request.rb +63 -0
- data/lib/virgil/sdk/client/request_signer.rb +90 -0
- data/lib/virgil/sdk/client/requests.rb +50 -0
- data/lib/virgil/sdk/client/requests/confirm_identity_request.rb +67 -0
- data/lib/virgil/sdk/client/requests/create_card_request.rb +105 -0
- data/lib/virgil/sdk/client/requests/revoke_card_request.rb +85 -0
- data/lib/virgil/sdk/client/requests/signable_request.rb +142 -0
- data/lib/virgil/sdk/client/requests/verify_identity_request.rb +60 -0
- data/lib/virgil/sdk/client/search_criteria.rb +79 -0
- data/lib/virgil/sdk/client/signatures_base64.rb +25 -0
- data/lib/virgil/sdk/client/virgil_client.rb +425 -0
- data/lib/virgil/sdk/cryptography.rb +42 -0
- data/lib/virgil/sdk/cryptography/hashes.rb +44 -0
- data/lib/virgil/sdk/cryptography/hashes/fingerprint.rb +79 -0
- data/lib/virgil/sdk/cryptography/hashes/hash_algorithm.rb +91 -0
- data/lib/virgil/sdk/cryptography/keys.rb +48 -0
- data/lib/virgil/sdk/cryptography/keys/key_pair.rb +46 -0
- data/lib/virgil/sdk/cryptography/keys/key_pair_type.rb +108 -0
- data/lib/virgil/sdk/cryptography/keys/key_storage.rb +177 -0
- data/lib/virgil/sdk/cryptography/keys/private_key.rb +44 -0
- data/lib/virgil/sdk/cryptography/keys/public_key.rb +44 -0
- data/lib/virgil/sdk/cryptography/keys/storage_item.rb +63 -0
- data/lib/virgil/sdk/cryptography/virgil_crypto.rb +411 -0
- data/lib/virgil/sdk/high_level.rb +21 -0
- data/lib/virgil/sdk/high_level/virgil_api.rb +71 -0
- data/lib/virgil/sdk/high_level/virgil_app_credentials.rb +54 -0
- data/lib/virgil/sdk/high_level/virgil_buffer.rb +161 -0
- data/lib/virgil/sdk/high_level/virgil_card.rb +204 -0
- data/lib/virgil/sdk/high_level/virgil_card_manager.rb +294 -0
- data/lib/virgil/sdk/high_level/virgil_card_verifier_info.rb +49 -0
- data/lib/virgil/sdk/high_level/virgil_context.rb +69 -0
- data/lib/virgil/sdk/high_level/virgil_identity.rb +17 -0
- data/lib/virgil/sdk/high_level/virgil_identity/email_confirmation.rb +60 -0
- data/lib/virgil/sdk/high_level/virgil_identity/validation_token.rb +49 -0
- data/lib/virgil/sdk/high_level/virgil_identity/verification_attempt.rb +69 -0
- data/lib/virgil/sdk/high_level/virgil_identity/verification_options.rb +56 -0
- data/lib/virgil/sdk/high_level/virgil_key.rb +168 -0
- data/lib/virgil/sdk/high_level/virgil_key_manager.rb +97 -0
- data/lib/virgil/sdk/version.rb +5 -0
- data/virgil-sdk.gemspec +31 -0
- metadata +203 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
# Copyright (C) 2016 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
|
36
|
+
module Virgil
|
37
|
+
module SDK
|
38
|
+
module Client
|
39
|
+
module Requests
|
40
|
+
# Revoke card signable API request.
|
41
|
+
class RevokeCardRequest < SignableRequest
|
42
|
+
|
43
|
+
# Class containing possible revocation reasons.
|
44
|
+
class Reasons
|
45
|
+
Unspecified = 'unspecified'
|
46
|
+
Compromised = 'compromised'
|
47
|
+
end
|
48
|
+
|
49
|
+
attr_accessor :card_id, :reason
|
50
|
+
|
51
|
+
# Constructs new CreateCardRequest object
|
52
|
+
def initialize(attributes)
|
53
|
+
super()
|
54
|
+
self.card_id = attributes[:card_id]
|
55
|
+
self.reason = attributes[:reason] || Reasons::Unspecified
|
56
|
+
end
|
57
|
+
|
58
|
+
# Restores request from snapshot model.
|
59
|
+
#
|
60
|
+
# Args:
|
61
|
+
# snapshot_model: snapshot model dict
|
62
|
+
def restore_from_snapshot_model(snapshot_model)
|
63
|
+
self.card_id = snapshot_model['card_id']
|
64
|
+
self.reason = snapshot_model['revocation_reason']
|
65
|
+
end
|
66
|
+
|
67
|
+
def restore(validation_token)
|
68
|
+
@validation_token = validation_token
|
69
|
+
end
|
70
|
+
|
71
|
+
# Constructs snapshot model for exporting and signing.
|
72
|
+
#
|
73
|
+
# Returns:
|
74
|
+
# Dict containing snapshot data model used for card revocation request.
|
75
|
+
def snapshot_model
|
76
|
+
return {
|
77
|
+
'card_id': self.card_id,
|
78
|
+
'revocation_reason': self.reason,
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# Copyright (C) 2016 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
require 'json'
|
36
|
+
require 'base64'
|
37
|
+
|
38
|
+
module Virgil
|
39
|
+
module SDK
|
40
|
+
module Client
|
41
|
+
module Requests
|
42
|
+
# Base class for all API requests.
|
43
|
+
class SignableRequest
|
44
|
+
extend SignaturesBase64
|
45
|
+
attr_reader :signatures, :snapshot, :validation_token
|
46
|
+
|
47
|
+
# protected :signatures=, :snapshot=
|
48
|
+
# attr_writer :snapshot
|
49
|
+
|
50
|
+
# Constructs new SignableRequest object
|
51
|
+
def initialize
|
52
|
+
@signatures = {}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Constructs snapshot model for exporting and signing.
|
56
|
+
#
|
57
|
+
# Should be implemented in the derived classes.
|
58
|
+
#
|
59
|
+
# Raises:
|
60
|
+
# NotImplementedError
|
61
|
+
def snapshot_model
|
62
|
+
raise NotImplementedError.new
|
63
|
+
end
|
64
|
+
|
65
|
+
# Restores request from snapshot model.
|
66
|
+
#
|
67
|
+
# Should be implemented in the derived classes.
|
68
|
+
#
|
69
|
+
# Args:
|
70
|
+
# snapshot: snapshot model dict
|
71
|
+
#
|
72
|
+
# Raises:
|
73
|
+
# NotImplementedError
|
74
|
+
def restore_from_snapshot_model(snapshot)
|
75
|
+
raise NotImplementedError.new
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Restores request from snapshot.
|
80
|
+
#
|
81
|
+
# Args:
|
82
|
+
# snapshot: Json-encoded snapshot request will be restored from.
|
83
|
+
# signatures: Request signatures.
|
84
|
+
def restore(snapshot, signatures, validation_token = nil)
|
85
|
+
@snapshot = snapshot
|
86
|
+
@signatures = signatures
|
87
|
+
@validation_token = validation_token
|
88
|
+
model = JSON.parse(Crypto::Bytes.new(snapshot).to_s)
|
89
|
+
restore_from_snapshot_model(model)
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Takes request data snapshot.
|
94
|
+
#
|
95
|
+
# Returns:
|
96
|
+
# Request snapshot bytes.
|
97
|
+
def take_snapshot
|
98
|
+
json_string = self.snapshot_model.to_json
|
99
|
+
Crypto::Bytes.from_string(json_string)
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# Exports request snapshot.
|
104
|
+
#
|
105
|
+
# Returns:
|
106
|
+
# base64-encoded json representation of the request model.
|
107
|
+
def export
|
108
|
+
json_string = self.request_model.to_json
|
109
|
+
Base64.strict_encode64(json_string)
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# Request data snapshot
|
114
|
+
def snapshot
|
115
|
+
@snapshot ||= self.take_snapshot
|
116
|
+
end
|
117
|
+
|
118
|
+
# Adds signature to request."""
|
119
|
+
def sign_with(fingerprint_id, signature)
|
120
|
+
@signatures[fingerprint_id] = signature
|
121
|
+
end
|
122
|
+
|
123
|
+
# Request model used for json representation.
|
124
|
+
def request_model
|
125
|
+
model = {
|
126
|
+
'content_snapshot': Base64.strict_encode64(snapshot.to_s),
|
127
|
+
'meta': {
|
128
|
+
'signs': signatures
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
if validation_token
|
133
|
+
model[:meta][:validation] = {'token': validation_token.value}
|
134
|
+
end
|
135
|
+
|
136
|
+
return model
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright (C) 2016 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
|
36
|
+
module Virgil
|
37
|
+
module SDK
|
38
|
+
module Client
|
39
|
+
module Requests
|
40
|
+
class VerifyIdentityRequest
|
41
|
+
attr_accessor :identity, :identity_type
|
42
|
+
private :identity_type=, :identity=
|
43
|
+
|
44
|
+
def initialize(identity, identity_type)
|
45
|
+
self.identity_type = identity_type
|
46
|
+
self.identity = identity
|
47
|
+
end
|
48
|
+
|
49
|
+
# Request model used for json representation.
|
50
|
+
def request_model
|
51
|
+
return {
|
52
|
+
'type': identity_type,
|
53
|
+
'value': identity
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright (C) 2016 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
module Virgil
|
36
|
+
module SDK
|
37
|
+
module Client
|
38
|
+
# Class holds criteria for searching Cards.
|
39
|
+
SearchCriteria = Struct.new(:identities, :identity_type, :scope) do
|
40
|
+
def initialize(identities, identity_type=nil, scope=nil)
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create new search criteria for searching cards by identity.
|
45
|
+
#
|
46
|
+
# Args:
|
47
|
+
# identity: VirgilIdentity value.
|
48
|
+
#
|
49
|
+
# Returns:
|
50
|
+
# Search criteria with provided identity.
|
51
|
+
def self.by_identity(identity)
|
52
|
+
return self.by_identities([identity])
|
53
|
+
end
|
54
|
+
|
55
|
+
# Create new search criteria for searching cards by identities.
|
56
|
+
#
|
57
|
+
# Args:
|
58
|
+
# identities: Identities value.
|
59
|
+
#
|
60
|
+
# Returns:
|
61
|
+
# Search criteria with provided identities.
|
62
|
+
def self.by_identities(identities)
|
63
|
+
return new(identities, nil, Card::APPLICATION)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Create new search criteria for searching cards by application bundle.
|
67
|
+
#
|
68
|
+
# Args:
|
69
|
+
# bundle: Application bundle.
|
70
|
+
#
|
71
|
+
# Returns:
|
72
|
+
# Search criteria for searching by bundle.
|
73
|
+
def self.by_app_bundle(bundle)
|
74
|
+
return new([bundle], 'application', Card::GLOBAL)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Virgil
|
2
|
+
module SDK
|
3
|
+
module Client
|
4
|
+
module SignaturesBase64
|
5
|
+
|
6
|
+
def signatures_to_base64(signatures_bytes)
|
7
|
+
encoded_signatures = {}
|
8
|
+
signatures_bytes.each do |key, val|
|
9
|
+
encoded_signatures[key] = Base64.strict_encode64(Virgil::Crypto::Bytes.new(val).to_s) #TODO
|
10
|
+
end
|
11
|
+
encoded_signatures
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def signatures_from_base64(signatures_base64)
|
16
|
+
decoded_signatures = {}
|
17
|
+
signatures_base64.each do |key, val|
|
18
|
+
decoded_signatures[key] = Virgil::Crypto::Bytes.from_base64(val)
|
19
|
+
end
|
20
|
+
decoded_signatures
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,425 @@
|
|
1
|
+
# Copyright (C) 2016 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
module Virgil
|
36
|
+
module SDK
|
37
|
+
module Client
|
38
|
+
# Virgil API client
|
39
|
+
#
|
40
|
+
# Contains methods for searching and managing cards.
|
41
|
+
class VirgilClient
|
42
|
+
# Exception raised when card is not valid
|
43
|
+
class InvalidCardException < StandardError
|
44
|
+
attr_reader :invalid_cards
|
45
|
+
|
46
|
+
def initialize(invalid_cards)
|
47
|
+
@invalid_cards = invalid_cards
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
"Cards #{@invalid_cards} are not valid"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_accessor :access_token, :cards_service_url, :identity_service_url,
|
56
|
+
:cards_read_only_service_url, :card_validator
|
57
|
+
|
58
|
+
# Constructs new VirgilClient object
|
59
|
+
def initialize(
|
60
|
+
access_token=nil,
|
61
|
+
cards_service_url=Card::SERVICE_URL,
|
62
|
+
cards_read_only_service_url=Card::READ_ONLY_SERVICE_URL,
|
63
|
+
identity_service_url=Virgil::SDK::VirgilIdentity::IDENTITY_SERVICE_URL
|
64
|
+
)
|
65
|
+
self.access_token = access_token
|
66
|
+
self.cards_service_url = cards_service_url
|
67
|
+
self.cards_read_only_service_url = cards_read_only_service_url
|
68
|
+
self.identity_service_url = identity_service_url
|
69
|
+
end
|
70
|
+
|
71
|
+
# Create published new card from given attributes.
|
72
|
+
#
|
73
|
+
# Args:
|
74
|
+
# identity: Created card identity.
|
75
|
+
# identity_type: Created card identity type.
|
76
|
+
# key_pair: Key pair of the created card.
|
77
|
+
# Public key is stored in the card, private key is used for request signing.
|
78
|
+
# app_id: Application identity for authority sign.
|
79
|
+
# app_key: Application key for authority sign.
|
80
|
+
#
|
81
|
+
# Returns:
|
82
|
+
# Created card from server response.
|
83
|
+
def create_card(identity, identity_type, key_pair, app_id, app_key)
|
84
|
+
request = Virgil::SDK::Client::Requests::CreateCardRequest.new(
|
85
|
+
identity: identity,
|
86
|
+
identity_type: identity_type,
|
87
|
+
scope: Client::Card::APPLICATION,
|
88
|
+
raw_public_key: self.crypto.export_public_key(key_pair.public_key)
|
89
|
+
)
|
90
|
+
self.request_signer.self_sign(request, key_pair.private_key)
|
91
|
+
self.request_signer.authority_sign(request, app_id, app_key)
|
92
|
+
|
93
|
+
return self.create_card_from_signed_request(request)
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# Create unpublished local card from given attributes.
|
98
|
+
#
|
99
|
+
# Args:
|
100
|
+
# identity: Created card identity.
|
101
|
+
# identity_type: Created card identity type.
|
102
|
+
# private_key: Private key of the created card.
|
103
|
+
# Public key is stored in the card, private key is used for request signing.
|
104
|
+
# app_id: Application identity for authority sign.
|
105
|
+
# app_key: Application key for authority sign.
|
106
|
+
# custom_data(optional): is an associative array that contains application specific
|
107
|
+
# parameters(under key :data) and information about the device
|
108
|
+
# on which the keypair was created(under key :device and :device_name).
|
109
|
+
# example: {data: {my_key1: "my_val1", my_key2: "my_val2"}, device: "iPhone6s", device_name: "Space grey one"}
|
110
|
+
#
|
111
|
+
# Returns:
|
112
|
+
# Created local card that is not published to Virgil Security services
|
113
|
+
def new_card(identity, identity_type, private_key, custom_data={})
|
114
|
+
data = custom_data[:data]
|
115
|
+
custom_data.delete(:data)
|
116
|
+
request = Virgil::SDK::Client::Requests::CreateCardRequest.new(
|
117
|
+
identity: identity,
|
118
|
+
identity_type: identity_type,
|
119
|
+
scope: Client::Card::APPLICATION,
|
120
|
+
raw_public_key: self.crypto.extract_public_key(private_key).value,
|
121
|
+
info: custom_data,
|
122
|
+
data: data
|
123
|
+
)
|
124
|
+
self.request_signer.self_sign(request, private_key)
|
125
|
+
|
126
|
+
return Client::Card.from_request_model(request.request_model)
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# Create unpublished global card from given attributes.
|
131
|
+
#
|
132
|
+
# Args:
|
133
|
+
# identity: Created card identity.
|
134
|
+
# identity_type: Created card identity type.
|
135
|
+
# private_key: Key pair of the created card.
|
136
|
+
# Public key is stored in the card, private key is used for request signing.
|
137
|
+
# custom_data(optional): is an associative array that contains application specific
|
138
|
+
# parameters(under key :data) and information about the device
|
139
|
+
# on which the keypair was created(under key :device and :device_name).
|
140
|
+
# example: {data: {my_key1: "my_val1", my_key2: "my_val2"}, device: "iPhone6s", device_name: "Space grey one"}
|
141
|
+
#
|
142
|
+
# Returns:
|
143
|
+
# Created global card that is not published to Virgil Security services
|
144
|
+
def new_global_card(identity, identity_type, private_key, custom_data={})
|
145
|
+
data = custom_data[:data]
|
146
|
+
custom_data.delete(:data)
|
147
|
+
request = Virgil::SDK::Client::Requests::CreateCardRequest.new(
|
148
|
+
identity: identity,
|
149
|
+
identity_type: identity_type,
|
150
|
+
scope: Client::Card::GLOBAL,
|
151
|
+
raw_public_key: self.crypto.extract_public_key(private_key).value,
|
152
|
+
info: custom_data,
|
153
|
+
data: data
|
154
|
+
)
|
155
|
+
self.request_signer.self_sign(request, private_key)
|
156
|
+
|
157
|
+
return Client::Card.from_request_model(request.request_model)
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
def sign_and_publish_card(card, app_id, app_key)
|
162
|
+
request = card.to_request
|
163
|
+
request_signer.authority_sign(
|
164
|
+
request,
|
165
|
+
app_id,
|
166
|
+
app_key
|
167
|
+
)
|
168
|
+
create_card_from_signed_request(request)
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
def publish_as_global_card(card)
|
173
|
+
request = card.to_request
|
174
|
+
create_card_from_signed_request(request)
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
# Create new card from signed creation request.
|
179
|
+
#
|
180
|
+
# Args:
|
181
|
+
# create_request: signed card creation request.
|
182
|
+
#
|
183
|
+
# Returns:
|
184
|
+
# Created card from server response.
|
185
|
+
#
|
186
|
+
# Raises:
|
187
|
+
# VirgilClient.InvalidCardException if client has validator
|
188
|
+
# and returned card signatures are not valid.
|
189
|
+
def create_card_from_signed_request(create_request)
|
190
|
+
http_request = Virgil::SDK::Client::HTTP::Request.new(
|
191
|
+
method: Virgil::SDK::Client::HTTP::Request::POST,
|
192
|
+
endpoint: "/#{Card::VRA_VERSION}/card",
|
193
|
+
body: create_request.request_model
|
194
|
+
)
|
195
|
+
raw_response = self.cards_connection.send_request(http_request)
|
196
|
+
card = Card.from_response(raw_response)
|
197
|
+
self.validate_cards([card]) if self.card_validator
|
198
|
+
card
|
199
|
+
end
|
200
|
+
|
201
|
+
def create_card_from_signed_request_async(create_request)
|
202
|
+
thread = Thread.new do
|
203
|
+
current = Thread.current
|
204
|
+
current[:card] = create_card_from_signed_request(create_request)
|
205
|
+
end
|
206
|
+
thread.join
|
207
|
+
thread[:card]
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
# Revoke card by id.
|
212
|
+
#
|
213
|
+
# Args:
|
214
|
+
# card_id: id of the revoked card.
|
215
|
+
# reason: card revocation reason.
|
216
|
+
# The possible values can be found in RevokeCardRequest::Reasons class.
|
217
|
+
# app_id: Application identity for authority sign.
|
218
|
+
# app_key: Application key for authority sign.
|
219
|
+
def revoke_card(
|
220
|
+
card_id,
|
221
|
+
app_id,
|
222
|
+
app_key,
|
223
|
+
reason=Requests::RevokeCardRequest::Reasons::Unspecified
|
224
|
+
)
|
225
|
+
request = Requests::RevokeCardRequest.new(
|
226
|
+
card_id: card_id,
|
227
|
+
reason: reason
|
228
|
+
)
|
229
|
+
self.request_signer.authority_sign(request, app_id, app_key)
|
230
|
+
|
231
|
+
self.revoke_card_from_signed_request(request)
|
232
|
+
end
|
233
|
+
|
234
|
+
|
235
|
+
def revoke_global_card(
|
236
|
+
card_id,
|
237
|
+
key_pair,
|
238
|
+
validation_token,
|
239
|
+
reason=Requests::RevokeCardRequest::Reasons::Unspecified
|
240
|
+
)
|
241
|
+
request = Requests::RevokeCardRequest.new(
|
242
|
+
card_id: card_id,
|
243
|
+
reason: reason
|
244
|
+
)
|
245
|
+
request.restore(validation_token)
|
246
|
+
self.request_signer.authority_sign(request, card_id, key_pair.private_key)
|
247
|
+
self.revoke_card_from_signed_request(request)
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
# Revoke card using signed revocation request.
|
252
|
+
#
|
253
|
+
# Args:
|
254
|
+
# revocation_request: signed card revocation request.
|
255
|
+
def revoke_card_from_signed_request(revocation_request)
|
256
|
+
http_request = Virgil::SDK::Client::HTTP::Request.new(
|
257
|
+
method: HTTP::Request::DELETE,
|
258
|
+
endpoint: "/#{Card::VRA_VERSION}/card/#{revocation_request.card_id}",
|
259
|
+
body: revocation_request.request_model
|
260
|
+
)
|
261
|
+
self.cards_connection.send_request(http_request)
|
262
|
+
end
|
263
|
+
|
264
|
+
def verify_identity(identity, identity_type)
|
265
|
+
verify_identity_request = Requests::VerifyIdentityRequest.new(identity, identity_type)
|
266
|
+
verify_identity_from_request(verify_identity_request)
|
267
|
+
end
|
268
|
+
|
269
|
+
def verify_identity_from_request(identity_request)
|
270
|
+
http_request = Virgil::SDK::Client::HTTP::Request.new(
|
271
|
+
method: HTTP::Request::POST,
|
272
|
+
endpoint: "/#{Card::VRA_VERSION}/verify",
|
273
|
+
body: identity_request.request_model
|
274
|
+
)
|
275
|
+
raw_response = self.identity_service_connection.send_request(http_request)
|
276
|
+
raw_response['action_id']
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
def confirm_identity(action_id, confirmation_code, time_to_live, count_to_live)
|
281
|
+
request = Requests::ConfirmIdentityRequest.new(confirmation_code, action_id, time_to_live, count_to_live)
|
282
|
+
confirm_identity_from_request(request)
|
283
|
+
end
|
284
|
+
|
285
|
+
def confirm_identity_from_request(confirm_request)
|
286
|
+
http_request = Virgil::SDK::Client::HTTP::Request.new(
|
287
|
+
method: HTTP::Request::POST,
|
288
|
+
endpoint: "/#{Card::VRA_VERSION}/confirm",
|
289
|
+
body: confirm_request.request_model
|
290
|
+
)
|
291
|
+
raw_response = self.identity_service_connection.send_request(http_request)
|
292
|
+
raw_response['validation_token']
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
# Get card by id.
|
297
|
+
#
|
298
|
+
# Args:
|
299
|
+
# card_id: id of the card to get.
|
300
|
+
#
|
301
|
+
# Returns:
|
302
|
+
# Found card from server response.
|
303
|
+
#
|
304
|
+
# Raises:
|
305
|
+
# VirgilClient::InvalidCardException if client has validator
|
306
|
+
# and retrieved card signatures are not valid.
|
307
|
+
def get_card(card_id)
|
308
|
+
# type: (str) -> Card
|
309
|
+
http_request = Virgil::SDK::Client::HTTP::Request.new(
|
310
|
+
method: HTTP::Request::GET,
|
311
|
+
endpoint: "/#{Card::VC_VERSION}/card/#{card_id}",
|
312
|
+
)
|
313
|
+
raw_response = self.read_cards_connection.send_request(http_request)
|
314
|
+
card = Card.from_response(raw_response)
|
315
|
+
self.validate_cards([card]) if self.card_validator
|
316
|
+
card
|
317
|
+
end
|
318
|
+
|
319
|
+
# Search cards by specified identities.
|
320
|
+
#
|
321
|
+
# Args:
|
322
|
+
# identities: identity values for search.
|
323
|
+
#
|
324
|
+
# Returns:
|
325
|
+
# Found cards from server response.
|
326
|
+
def search_cards_by_identities(*identities)
|
327
|
+
return self.search_cards_by_criteria(
|
328
|
+
SearchCriteria.by_identities(identities)
|
329
|
+
)
|
330
|
+
end
|
331
|
+
|
332
|
+
# Search cards by specified app bundle.
|
333
|
+
#
|
334
|
+
# Args:
|
335
|
+
# bundle: application bundle for search.
|
336
|
+
#
|
337
|
+
# Returns:
|
338
|
+
# Found cards from server response.
|
339
|
+
def search_cards_by_app_bundle(bundle)
|
340
|
+
return self.search_cards_by_criteria(
|
341
|
+
SearchCriteria.by_app_bundle(bundle)
|
342
|
+
)
|
343
|
+
end
|
344
|
+
|
345
|
+
# Search cards by specified search criteria.
|
346
|
+
#
|
347
|
+
# Args:
|
348
|
+
# search_criteria: constructed search criteria.
|
349
|
+
#
|
350
|
+
# Returns:
|
351
|
+
# Found cards from server response.
|
352
|
+
#
|
353
|
+
# Raises:
|
354
|
+
# VirgilClient.InvalidCardException if client has validator
|
355
|
+
# and cards are not valid.
|
356
|
+
def search_cards_by_criteria(search_criteria)
|
357
|
+
body = {identities: search_criteria.identities}
|
358
|
+
if search_criteria.identity_type
|
359
|
+
body[:identity_type] = search_criteria.identity_type
|
360
|
+
end
|
361
|
+
if search_criteria.scope == Card::GLOBAL
|
362
|
+
body[:scope] = Card::GLOBAL
|
363
|
+
end
|
364
|
+
http_request = Virgil::SDK::Client::HTTP::Request.new(
|
365
|
+
method: HTTP::Request::POST,
|
366
|
+
endpoint: "/#{Card::VC_VERSION}/card/actions/search",
|
367
|
+
body: body,
|
368
|
+
)
|
369
|
+
response = self.read_cards_connection.send_request(http_request)
|
370
|
+
cards = response.map { |card| Card.from_response(card) }
|
371
|
+
self.validate_cards(cards) if self.card_validator
|
372
|
+
return cards
|
373
|
+
end
|
374
|
+
|
375
|
+
# Validate cards signatures.
|
376
|
+
# Args:
|
377
|
+
# cards: list of cards to validate.
|
378
|
+
#
|
379
|
+
# Raises:
|
380
|
+
# VirgilClient::InvalidCardException if some cards are not valid.
|
381
|
+
def validate_cards(cards)
|
382
|
+
invalid_cards = cards.select { |card| !card_validator.is_valid?(card) }
|
383
|
+
if invalid_cards.any?
|
384
|
+
raise InvalidCardException.new(invalid_cards)
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
# Cards service connection used for creating and revoking cards.
|
389
|
+
def cards_connection
|
390
|
+
@_cards_connection ||= HTTP::CardsServiceConnection.new(
|
391
|
+
self.access_token,
|
392
|
+
self.cards_service_url
|
393
|
+
)
|
394
|
+
end
|
395
|
+
|
396
|
+
# Cards service connection used for getting and searching cards.
|
397
|
+
def read_cards_connection
|
398
|
+
@_read_cards_connection = HTTP::CardsServiceConnection.new(
|
399
|
+
self.access_token,
|
400
|
+
self.cards_read_only_service_url
|
401
|
+
)
|
402
|
+
end
|
403
|
+
|
404
|
+
|
405
|
+
def identity_service_connection
|
406
|
+
@identity_service_connection = HTTP::CardsServiceConnection.new(
|
407
|
+
nil,
|
408
|
+
self.identity_service_url
|
409
|
+
)
|
410
|
+
|
411
|
+
end
|
412
|
+
|
413
|
+
# Request signer for signing constructed requests.
|
414
|
+
def request_signer
|
415
|
+
@_request_signer ||= RequestSigner.new(self.crypto)
|
416
|
+
end
|
417
|
+
|
418
|
+
# Crypto library wrapper.
|
419
|
+
def crypto
|
420
|
+
@_crypto ||= Virgil::SDK::Cryptography::VirgilCrypto.new
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|