roqs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f19a8901d58a30e6f96bc3a69edd4674c5a2c64bc9acc017b806c6617961c0dd
4
+ data.tar.gz: 86a3ad02995a7d908818d11d185510faee8ead854611266737af43fe5f2410b1
5
+ SHA512:
6
+ metadata.gz: fe26fcb62c00f7622d35d2560b3183fab2d2917b4b90755fd58ffeaedbd4ceda0ca1faf405ed4e84a2baea5ab890ce085760bad4826fda434c7cc29964ab53c6
7
+ data.tar.gz: 16a08e37b93c050424969e5a64dce0a780379304cabf1d864bfb91d838a73f74bb4b89aebffa45e7edb44344f3061508bef2e2ec656122dd4718556b3d485544
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ AllCops:
2
+ DisabledByDefault: true
data/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # Roqs
2
+
3
+ Roqs is the Ruby wrapper to the [Open Quantum Safe library](https://openquantumsafe.org). The native library was tested against the liboqs at [liboqs](https://github.com/open-quantum-safe/liboqs)
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'roqs'
10
+ ```
11
+
12
+ And then execute:
13
+
14
+ $ bundle install
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install roqs
19
+
20
+ ## Usage
21
+
22
+ OQS mainly only has two group of functions: Key Encapsulation Mechanism (KEM) and Signature (SIG).
23
+
24
+ Therefore the Ruby wrapper abstraction is following the liboqs C version as baseline.
25
+
26
+ ### Key Encapsulation Mechanism (KEM)
27
+
28
+ For KEM, the API is simple:
29
+
30
+ 1. List all supported KEM PQ algorithms - PQ algorithms can be enable or disabled at compile time so it all depends on the liboqs native library. This API listed down the algorithms which are *supported* as reported by the native library. If you're using your own version of the library, you might have different output.
31
+ ```ruby
32
+ require 'roqs'
33
+
34
+ supported_algo = Roqs::KEM.supported_kem_algo
35
+ supported_algo.each do |al|
36
+ # al is the algorithm name (string) which is required by subsequent API
37
+ ...
38
+ end
39
+ ```
40
+
41
+ 2. Generate keypair
42
+ ```ruby
43
+ require 'roqs'
44
+
45
+ kyber = Roqs::KEM.new('Kyber768')
46
+ pubKey, secretKey = kyber.genkeypair
47
+ # note pubKey and secretKey (or private key) is Fiddle::Pointer type and
48
+ # is required to be used by the C API in the subsequent phase.
49
+ # Note that pubKey and secretKey are required to be free manually
50
+ # Refer spec file for usage
51
+ ```
52
+
53
+ 3. Key encapsulation - KEM is meant for key encapsulation which similar with Diffie-Hellman kind of key exchange
54
+ ```ruby
55
+ require 'roqs'
56
+
57
+ sessionKey, cipher = kyber.derive_encapsulation_key(pubKey)
58
+ # cipher is required to be sent to recipient end to re-generate the sessionKey at recipient end.
59
+ # Returned sessionKey is meant to convert into the final AES (or any other symmetric key)
60
+ # for the actual data encryption
61
+ ```
62
+
63
+ 4. Key decapsulation - Re-generate the session key from the private key
64
+ ```ruby
65
+ require 'roqs'
66
+
67
+ sessionKey = kyber.derive_decapsulation_key(cipher, secretKey)
68
+ # cipher is given by sender and privKey is the recipient own private key
69
+ ```
70
+
71
+ _sessionKey_ returned from derive\_encapsulation\_key() shall be same as the _sessionKey_ from derive\_decapsulation\_key(). That session key shall be the AES key (any other symmetric key) for the data encryption.
72
+
73
+
74
+ ### Signature mechanism
75
+
76
+ Signature mechanism is similar with KEM.
77
+
78
+ 1. List all supported Signature PQ algorithms - It is same as KEM as algorithm can be turned on or off during compile time
79
+ ```ruby
80
+ require 'roqs'
81
+
82
+ supported_algo = Roqs::SIG.supported_signature_algo
83
+ supported_algo.each do |al|
84
+ # al is the algorithm name (string) which is required by subsequent API
85
+ ...
86
+ end
87
+ ```
88
+
89
+ 2. Generate keypair
90
+ ```ruby
91
+ require 'roqs'
92
+
93
+ dili = Roqs::SIG.new('Dilithium5')
94
+ pubKey, secretKey = dili.genkeypair
95
+ # note pubKey and secretKey (or private key) is Fiddle::Pointer type and
96
+ # is required to be used by the C API in the subsequent phase.
97
+ # Note that pubKey and secretKey are required to be free manually
98
+ # Refer spec file for usage
99
+ ```
100
+
101
+ 3. Generate data signature
102
+ ```rubyion
103
+ require 'roqs'
104
+
105
+ # sign data using sender secretKey/private key
106
+ signature = dili.sign("this is message", secretKey)
107
+ ```
108
+
109
+ 4. Verify data signature
110
+ ```ruby
111
+ require 'roqs'
112
+
113
+ # verify signature with given data using sender public key
114
+ res = dili.verify("this is message", signature, pubKey)
115
+ # res is boolean to indicate the signature verification is passed or failed
116
+ ```
117
+
118
+ spec folder has the necessary API example usage.
119
+
120
+
121
+ ## Test Results
122
+
123
+ Refer to [test result](https://github.com/chrisliaw/liboqs-ruby/blob/master/TEST-RESULT.md) for details.
124
+
125
+ ## License
126
+
127
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
128
+
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
9
+ require 'release/gem'
data/TEST-RESULT.md ADDED
@@ -0,0 +1,68 @@
1
+
2
+ # The following are test results for release roqs-0.1.0
3
+
4
+ liboqs-0.9.0 has less PQ algorithms and includes all 4 + 3 of the [finalist in the NIST PQC Standardization Candidates](https://csrc.nist.gov/news/2022/pqc-candidates-to-be-standardized-and-round-4)
5
+ ## Development Environment
6
+
7
+ The source code was tested on
8
+ * Linux: Ruby MRI 3.2.1 (2023-02-08 revision 31819e82c8) [x86\_64-linux], Linux Mint 21.2 x86\_64, Kernel 5.15.0-88-generic, CMake version 3.22.1, Ninja 1.10.1
9
+
10
+ ## Testing result
11
+
12
+ The following test result is by running the rspec.
13
+
14
+ The compiled liboqs version 0.9.0 library on Linux works flawlessly.
15
+
16
+ Unfornately I've lost access to MacOS. Any help would be gladely appreciated.
17
+
18
+ All KEM and SIG algos supported completed all major operations such as keygen, sign/verify, encap/decap without error.
19
+
20
+
21
+ ### Windows (Coming Soon)
22
+
23
+ # The following are the test results for liboqs version 0.7.0 (before NIST finalist was published. It may not relevent for now just for history purposes)
24
+ ## Development Environment
25
+
26
+ The source code was tested on
27
+ * Linux: Ruby MRI 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux], Linux Mint 20.2 x86_64, Kernel 5.4.0-81-generic, Intel i7-9750H, CMake version 3.16.3, Ninja 1.10.0
28
+ * MacOS: Ruby MRI 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86\_64-darwin20], Mac OS BigSur 11.5, 2.5GHz Quad-Core Intel Core i7, Apple clang version 12.0.5 (clang-1205.0.22.11), CMake version 3.21.1, Ninja 1.10.2
29
+ * Windows: Ruby MRI 3.0.2p107 (2021-07-07 revision 0db68f02333) [x64-mingw32], Windows 10 64 bits, Microsoft C/C++ compiler v 19.25.28610.4, Intel i7-9750H, CMake version 3.16.19112601-MSVC\_2, Ninja 1.8.2
30
+
31
+ ## Testing result
32
+
33
+ The following test result is by running the rspec.
34
+
35
+ The compiled liboqs version 0.7.0 library on Linux works flawlessly on respective OS.
36
+
37
+ All KEM and SIG algos supported completed all major operations such as keygen, sign/verify, encap/decap without error.
38
+
39
+
40
+ ### Windows (Cross Compiling)
41
+
42
+ Cross compiling DLL for Windows on Linux with MingW toolchain failed with:
43
+ For KEM:
44
+ * BIKE-L1 & BIKE-L3 failed where library return null. Both running ok on Linux and MacOS
45
+ * Stack level too deep with all Classic-McEliece family of algo. All algo of Classic-McEliece-xxxx not able to execute.
46
+ * Stagmentation fault for SIDH-p503, SIDH-p503-compressed, SIDH-p751, SIDH-p751-compressed, SIKE-p503, SIKE-p751, SIKE-p503-compressed and SIKE-p751-compressed
47
+
48
+ For SIG:
49
+ * Stack level too deep for Rainbow-V-Classic, Rainbow-V-Circumzenithal and Rainbow-V-Compressed
50
+
51
+ Test cases not able to proceed after "Stack level too deep" exception. Not sure due to Ruby or native library
52
+
53
+ ### Windows (Native build)
54
+
55
+ Native compile oqs library on Windows however have different result:
56
+ For KEM:
57
+ * BIKE-L1 & BIKE-L3 failed where library return null. Both running ok on Linux and MacOS
58
+ * Stack level too deep with all Classic-McEliece family of algo. All algo of Classic-McEliece-xxxx not able to execute.
59
+
60
+ For SIG
61
+ * Rainbow-V still crash
62
+
63
+ Rainbow feels taking longer time on Windows compare to Linux/Mac?
64
+ Sphincs slow too
65
+
66
+ But SIDH-xxx and SIKE-xxx family passed on native build
67
+
68
+
@@ -0,0 +1,20 @@
1
+
2
+ require 'fiddle'
3
+ require 'fiddle/import'
4
+
5
+ module Roqs
6
+ module CommonWrapper
7
+ extend Fiddle::Importer
8
+ include Roqs::Wrapper
9
+
10
+ #dlload File.join(File.dirname(__FILE__),"..","..","native","linux","x86_64","liboqs.so.0.7.0")
11
+ load_oqs_lib
12
+
13
+ extern 'int OQS_MEM_secure_bcmp(const void *a, const void *b, size_t len)'
14
+ extern 'int OQS_MEM_cleanse(const void *ptr, size_t len)'
15
+ extern 'int OQS_MEM_secure_free(void *ptr, size_t len)'
16
+ extern 'int OQS_MEM_insecure_free(void *ptr)'
17
+
18
+
19
+ end
20
+ end
data/lib/roqs/kem.rb ADDED
@@ -0,0 +1,148 @@
1
+
2
+ require_relative 'struct'
3
+ require_relative 'kem_wrapper'
4
+ require_relative 'common_wrapper'
5
+
6
+ require_relative 'kem_public_key'
7
+
8
+ module Roqs
9
+ class KEM
10
+
11
+ def self.supported_kem_algo
12
+ ttl = KEMWrapper.OQS_KEM_alg_count
13
+ supported = []
14
+ (0...ttl).each do |i|
15
+ pName = KEMWrapper.OQS_KEM_alg_identifier(i)
16
+ name = pName.to_s
17
+ st = KEMWrapper.OQS_KEM_alg_is_enabled(name)
18
+ if st
19
+ supported << name
20
+ end
21
+ end
22
+
23
+ supported
24
+ end
25
+
26
+ def initialize(name)
27
+ @algo = name
28
+ oqsKem = KEMWrapper.OQS_KEM_new(@algo)
29
+ raise Error, "Unable to create object '#{@algo}'. It is either the algorithm not supported or it is disabled at compile time." if oqsKem.null?
30
+ @struct = OQS_KEM.new(oqsKem)
31
+ end
32
+
33
+ def cleanup
34
+ KEMWrapper.OQS_KEM_free(@struct) if not @struct.nil?
35
+ end
36
+
37
+ def free(obj)
38
+ obj.free if not (obj.nil? and obj.null?)
39
+ end
40
+
41
+ def intrinsic_name
42
+ @struct.intrinsic_name.to_s
43
+ end
44
+
45
+ def algo_version
46
+ @struct.algo_version.to_s
47
+ end
48
+
49
+ def method_missing(mtd, *args, &block)
50
+ @struct.send(mtd) if not @struct.nil? and @struct.respond_to?(mtd)
51
+ end
52
+
53
+ def genkeypair
54
+ pubKey = Fiddle::Pointer.malloc(@struct.length_public_key, Fiddle::RUBY_FREE)
55
+ raise Error, "Unable to allocate memory for public key size #{@struct.length_public_key}" if pubKey.null?
56
+ privKey = Fiddle::Pointer.malloc(@struct.length_secret_key, Fiddle::RUBY_FREE)
57
+ raise Error, "Unable to allocate memory for secret key size #{@struct.length_secret_key}" if privKey.null?
58
+
59
+ rv = KEMWrapper.OQS_KEM_keypair(@struct, pubKey, privKey)
60
+ raise Error, "Error in generation of keypair" if rv != Roqs::OQS_SUCCESS
61
+
62
+ #pubKeyBin = pubKey[0, pubKey.size]
63
+ #privKeyBin = privKey[0, privKey.size]
64
+
65
+ [KEMPublicKey.new(pubKey), privKey]
66
+ end
67
+
68
+ def derive_encapsulation_key(pubKey)
69
+
70
+ cipher = Fiddle::Pointer.malloc(@struct.length_ciphertext, Fiddle::RUBY_FREE)
71
+ raise Error, "Unable to allocate memory for ciphertext size #{@struct.length_ciphertext}" if cipher.null?
72
+
73
+ encpKey = Fiddle::Pointer.malloc(@struct.length_shared_secret, Fiddle::RUBY_FREE)
74
+ raise Error, "Unable to allocate memory for shared secret size #{@struct.length_shared_secret}" if encpKey.null?
75
+
76
+ rv = KEMWrapper.OQS_KEM_encaps(@struct, cipher, encpKey, pubKey)
77
+ raise Error, "Error in encapsulation" if rv != Roqs::OQS_SUCCESS
78
+
79
+ encpKeyBin = encpKey[0,encpKey.size]
80
+ cipherBin = cipher[0,cipher.size]
81
+
82
+ cipher.free
83
+ encpKey.free
84
+
85
+ [encpKeyBin, cipherBin]
86
+
87
+ end
88
+
89
+ def derive_decapsulation_key(cipherBin, privKey)
90
+
91
+ raise Error, "Cipher cannot be empty" if cipherBin.nil?
92
+ raise Error, "Private key cannot be nil" if privKey.nil?
93
+
94
+ encpKey = Fiddle::Pointer.malloc(@struct.length_shared_secret, Fiddle::RUBY_FREE)
95
+ raise Error, "Unable to allocate memory for shared secret size #{@struct.length_shared_secret}" if encpKey.null?
96
+
97
+ rv = KEMWrapper.OQS_KEM_decaps(@struct, encpKey , cipherBin, privKey)
98
+ raise Error, "Error in decapsulation" if rv != Roqs::OQS_SUCCESS
99
+
100
+ encpKeyBin = encpKey[0,encpKey.size]
101
+
102
+ encpKey.free
103
+
104
+ encpKeyBin
105
+
106
+ end
107
+
108
+ #def test
109
+
110
+ # @cipher = Fiddle::Pointer.malloc(@struct.length_ciphertext, Fiddle::RUBY_FREE)
111
+ # raise Error, "Unable to allocate memory for ciphertext size #{@struct.length_ciphertext}" if @cipher.null?
112
+
113
+ # shared_e = Fiddle::Pointer.malloc(@struct.length_shared_secret, Fiddle::RUBY_FREE)
114
+ # raise Error, "Unable to allocate memory for shared secret size #{@struct.length_shared_secret}" if shared_e.null?
115
+ #
116
+ # shared_d = Fiddle::Pointer.malloc(@struct.length_shared_secret, Fiddle::RUBY_FREE)
117
+ # raise Error, "Unable to allocate memory for shared secret size #{@struct.length_shared_secret}" if shared_d.null?
118
+
119
+ # shared_x = Fiddle::Pointer.malloc(@struct.length_shared_secret, Fiddle::RUBY_FREE)
120
+ #
121
+ # p shared_e.ptr == shared_d.ptr
122
+
123
+ # rb = shared_e[0, shared_e.size]
124
+ # p rb
125
+
126
+ # rv = KEMWrapper.OQS_KEM_encaps(@struct, @cipher, shared_e, @pubKey)
127
+ # raise Error, "Error in encapsulation" if rv != KEMWrapper::OQS_SUCCESS
128
+
129
+ # rb = shared_e[0, shared_e.size]
130
+ # p rb
131
+
132
+ # p shared_e.ptr == shared_d.ptr
133
+
134
+ # rv = KEMWrapper.OQS_KEM_decaps(@struct, shared_d, @cipher, @privKey)
135
+ # raise Error, "Error in decapsulation" if rv != KEMWrapper::OQS_SUCCESS
136
+
137
+ # p shared_e.ptr == shared_d.ptr
138
+
139
+ # p shared_d.size
140
+ # rb = shared_d[0, shared_d.size]
141
+ # p rb
142
+
143
+
144
+ #end
145
+
146
+ end
147
+
148
+ end
@@ -0,0 +1,28 @@
1
+
2
+ require_relative 'struct'
3
+ require_relative 'kem_wrapper'
4
+ require_relative 'common_wrapper'
5
+
6
+ module Roqs
7
+ class KEMPublicKey
8
+
9
+ def initialize(nativePubKey)
10
+ @native_pubkey = nativePubKey
11
+ end
12
+
13
+ def length
14
+ @native_pubkey.size
15
+ end
16
+
17
+ def bytes
18
+ #puts "raw 1 : #{@native_pubkey.size}"
19
+ #puts "raw 2 : #{@native_pubkey.to_str}"
20
+ @native_pubkey.to_str
21
+ end
22
+
23
+ def native_pubkey
24
+ @native_pubkey
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+
2
+ require 'fiddle'
3
+ require 'fiddle/import'
4
+
5
+ require_relative 'wrapper'
6
+
7
+ module Roqs
8
+ module KEMWrapper
9
+ extend Fiddle::Importer
10
+ include Roqs::Wrapper
11
+
12
+ #dlload File.join(File.dirname(__FILE__),"..","..","native","linux","x86_64","liboqs.so.0.7.0")
13
+ load_oqs_lib
14
+
15
+ extern 'const char * OQS_KEM_alg_identifier(size_t i)'
16
+ extern 'int OQS_KEM_alg_count(void)'
17
+ extern 'int OQS_KEM_alg_is_enabled(const char * name)'
18
+
19
+ extern 'OQS_KEM * OQS_KEM_new(const char * algo)'
20
+ extern 'void OQS_KEM_free(OQS_KEM * kem)'
21
+
22
+ extern 'int OQS_KEM_keypair(const OQS_KEM *kem, uint8_t *public_key, uint8_t *secret_key)'
23
+
24
+ extern 'int OQS_KEM_encaps(const OQS_KEM *kem, uint8_t * ciphertext, uint8_t *shared_secret, uint8_t *public_key)'
25
+ extern 'int OQS_KEM_decaps(const OQS_KEM *kem, uint8_t * shared_secret, uint8_t *ciphertext, uint8_t *secret_key)'
26
+
27
+ end
28
+ end
data/lib/roqs/sig.rb ADDED
@@ -0,0 +1,99 @@
1
+
2
+ require_relative 'struct'
3
+ require_relative 'sig_wrapper'
4
+ require_relative 'common_wrapper'
5
+
6
+ module Roqs
7
+ class SIG
8
+
9
+ def self.supported_signature_algo
10
+ ttl = SIGWrapper.OQS_SIG_alg_count
11
+ supported = []
12
+ (0...ttl).each do |i|
13
+ pName = SIGWrapper.OQS_SIG_alg_identifier(i)
14
+ name = pName.to_s
15
+ st = SIGWrapper.OQS_SIG_alg_is_enabled(name)
16
+ if st
17
+ supported << name
18
+ end
19
+ end
20
+
21
+ supported
22
+ end
23
+
24
+ def initialize(name)
25
+ @algo = name
26
+ oqsSig = SIGWrapper.OQS_SIG_new(@algo)
27
+ raise Error, "Unable to create object '#{@algo}'. It is either the algorithm not supported or it is disabled at compile time." if oqsSig.null?
28
+ @struct = OQS_SIG.new(oqsSig)
29
+ end
30
+
31
+ def cleanup
32
+ SIGWrapper.OQS_SIG_free(@struct) if not @struct.nil?
33
+ end
34
+
35
+ def free(obj)
36
+ obj.free if not (obj.nil? and obj.null?)
37
+ end
38
+
39
+ def intrinsic_name
40
+ @struct.intrinsic_name.to_s
41
+ end
42
+
43
+ def algo_version
44
+ @struct.algo_version.to_s
45
+ end
46
+
47
+ def method_missing(mtd, *args, &block)
48
+ @struct.send(mtd) if not @struct.nil? and @struct.respond_to?(mtd)
49
+ end
50
+
51
+ def genkeypair
52
+ pubKey = Fiddle::Pointer.malloc(@struct.length_public_key, Fiddle::RUBY_FREE)
53
+ raise Error, "Unable to allocate memory for public key size #{@struct.length_public_key}" if pubKey.null?
54
+ privKey = Fiddle::Pointer.malloc(@struct.length_secret_key, Fiddle::RUBY_FREE)
55
+ raise Error, "Unable to allocate memory for secret key size #{@struct.length_secret_key}" if privKey.null?
56
+
57
+ rv = SIGWrapper.OQS_SIG_keypair(@struct, pubKey, privKey)
58
+ raise Error, "Error in generation of keypair" if rv != Roqs::OQS_SUCCESS
59
+
60
+ [pubKey, privKey]
61
+ end
62
+
63
+ def verify(message,signature,pubKey)
64
+
65
+ pMessage = Fiddle::Pointer.to_ptr(message)
66
+ pSignature = Fiddle::Pointer.to_ptr(signature)
67
+
68
+ rv = SIGWrapper.OQS_SIG_verify(@struct, pMessage, message.length, pSignature, signature.length, pubKey)
69
+
70
+ rv == Roqs::OQS_SUCCESS
71
+
72
+ end
73
+
74
+ def sign(message, privKey)
75
+
76
+ raise Error, "Private key cannot be nil" if privKey.nil?
77
+
78
+ signature = Fiddle::Pointer.malloc(@struct.length_signature, Fiddle::RUBY_FREE)
79
+ raise Error, "Unable to allocate memory for signature size #{@struct.length_signature}" if signature.null?
80
+ signLen = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T, Fiddle::RUBY_FREE)
81
+ raise Error, "Unable to allocate memory for signature length size #{Fiddle::SIZEOF_SIZE_T}" if signLen.null?
82
+
83
+ pMessage = Fiddle::Pointer.to_ptr(message)
84
+
85
+ rv = SIGWrapper.OQS_SIG_sign(@struct, signature, signLen, pMessage, message.length, privKey)
86
+ raise Error, "Error in signing" if rv != Roqs::OQS_SUCCESS
87
+
88
+ signBin = signature[0, signLen.ptr.to_i]
89
+
90
+ signLen.free
91
+ signature.free
92
+
93
+ signBin
94
+
95
+ end
96
+
97
+ end
98
+
99
+ end
@@ -0,0 +1,31 @@
1
+
2
+ require 'fiddle'
3
+ require 'fiddle/import'
4
+
5
+ module Roqs
6
+ module SIGWrapper
7
+ extend Fiddle::Importer
8
+ include Roqs::Wrapper
9
+
10
+ ## OQS_STATUS
11
+ #OQS_ERROR = -1
12
+ #OQS_SUCCESS = 0
13
+ #OQS_EXTERNAL_LIB_ERROR_OPENSSL = 50
14
+
15
+ #dlload File.join(File.dirname(__FILE__),"..","..","native","linux","x86_64","liboqs.so.0.7.0")
16
+ load_oqs_lib
17
+
18
+ extern 'const char * OQS_SIG_alg_identifier(size_t i)'
19
+ extern 'int OQS_SIG_alg_count(void)'
20
+ extern 'int OQS_SIG_alg_is_enabled(const char * name)'
21
+
22
+ extern 'OQS_SIG * OQS_SIG_new(const char * algo)'
23
+ extern 'void OQS_SIG_free(OQS_SIG * sig)'
24
+
25
+ extern 'int OQS_SIG_keypair(const OQS_SIG *sig, uint8_t *public_key, uint8_t *secret_key)'
26
+
27
+ extern 'int OQS_SIG_sign(const OQS_SIG *sig, uint8_t * signature, size_t *signature_len, uint8_t *message, size_t message_len, uint8_t *secret_key)'
28
+ extern 'int OQS_SIG_verify(const OQS_SIG *sig, uint8_t * message, size_t message_len, uint8_t *signature, size_t signature_len, uint8_t *public_key)'
29
+
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+
2
+ require 'fiddle'
3
+ require 'fiddle/import'
4
+
5
+ module Roqs
6
+ extend Fiddle::Importer
7
+
8
+ OQS_KEM = struct [
9
+ "const char * intrinsic_name",
10
+ "const char * algo_version",
11
+ "uint8_t claimed_nist_level",
12
+ "int ind_cca",
13
+ "size_t length_public_key",
14
+ "size_t length_secret_key",
15
+ "size_t length_ciphertext",
16
+ "size_t length_shared_secret",
17
+ "int (*keypair)(uint8_t *pubKey, uint8_t* secretKey)",
18
+ "int (*encaps)(uint8_t *cipher_text, uint8_t* shared_secret, const unit8_t * pubKey)",
19
+ "int (*decaps)(uint8_t *shared_secret, uint8_t* cipher_text, const unit8_t * secretKey)"
20
+ ]
21
+
22
+ OQS_SIG = struct [
23
+ "const char * intrinsic_name",
24
+ "const char * algo_version",
25
+ "uint8_t claimed_nist_level",
26
+ "int euf_cma",
27
+ "size_t length_public_key",
28
+ "size_t length_secret_key",
29
+ "size_t length_signature",
30
+ "int (*keypair)(uint8_t *pubKey, uint8_t* secretKey)",
31
+ "int (*sign)(uint8_t *signature, size_t signature_len, const uint8_t* message, size_t message_len, const unit8_t * secretKey)",
32
+ "int (*verify)(uint8_t *message, size_t message_len, const uint8_t* signature, size_t signature_len, const unit8_t * pubKey)"
33
+ ]
34
+
35
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roqs
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,79 @@
1
+
2
+ require 'fiddle'
3
+
4
+ module Roqs
5
+ module Wrapper
6
+ class WrapperError < StandardError; end
7
+
8
+ module ClassMethods
9
+ def load_oqs_lib
10
+ os = detect_os
11
+ logger.debug "Found OS #{os}"
12
+ load_arch_lib(os)
13
+ end
14
+
15
+ def detect_os
16
+ plat = RUBY_PLATFORM
17
+ if plat =~ /linux/
18
+ :linux
19
+ elsif plat =~ /darwin/
20
+ :macos
21
+ elsif plat =~ /mingw/
22
+ :windows
23
+ else
24
+ raise WrapperError, "Unknown platform detected. [#{plat}]"
25
+ end
26
+ end
27
+
28
+ def load_arch_lib(os)
29
+ plat = RUBY_PLATFORM
30
+ pplat = plat.split('-')[0]
31
+ logger.debug "OS architecture is #{pplat}"
32
+ usrDrvDir = ENV['ROQS_LIBOQS_DIR']
33
+ if not_empty?(usrDrvDir)
34
+ logger.debug "Load liboqs shared library from user provided root : #{File.join(usrDrvDir, pplat)}"
35
+ drvDir = File.join(usrDrvDir,pplat)
36
+ else
37
+ logger.debug "Load liboqs shared library from Roqs internal root : #{File.join(File.dirname(__FILE__),"..","..","native","#{os}",pplat)}"
38
+ drvDir = File.join(File.dirname(__FILE__),"..","..","native","#{os}",pplat)
39
+ end
40
+
41
+ if File.exist?(drvDir)
42
+ Dir.glob(File.join(drvDir,"liboqs*")) do |f|
43
+ logger.debug "Loading liboqs at : #{f}"
44
+ dlload f
45
+ end
46
+ else
47
+ errMsg = []
48
+ errMsg << "Shared library of liboqs (https://github.com/open-quantum-safe/liboqs) could not be found at '#{drvDir}'"
49
+ errMsg << "You might need to compile for your platform."
50
+ errMsg << "Simply follow the steps beflow:"
51
+ errMsg << "1. Clone the repository at https://github.com/open-quantum-safe/liboqs"
52
+ errMsg << " > clone https://github.com/open-quantum-safe/liboqs liboqs"
53
+ errMsg << "2. Make sure all pre-requisites are installed as documented here : https://github.com/open-quantum-safe/liboqs#quickstart"
54
+ errMsg << "3. Run the following commands: "
55
+ errMsg << " > cd liboqs && mkdir build && cd build"
56
+ errMsg << " > cmake -GNinja .. -DBUILD_SHARED_LIBS=ON"
57
+ errMsg << " > ninja"
58
+ errMsg << "4. Shared library shall be built under lib dir."
59
+ errMsg << "5. Copy the shared library into '#{drvDir}' and you should be good to go"
60
+ errMsg << " Note: System shall read env variable 'ROQS_LIBOQS_DIR' to decide where to load the liboqs dynamic library from."
61
+ errMsg << " If no value is given, system shall load from default path : #{File.join(File.dirname(__FILE__),"..","..","native","#{os}",pplat)}"
62
+ raise WrapperError, errMsg.join("\n")
63
+ end
64
+ end
65
+
66
+ def logger
67
+ Roqs.logger(:roqs_wrapper)
68
+ end
69
+ end
70
+ def self.included(klass)
71
+ klass.extend(ClassMethods)
72
+ end
73
+
74
+ def logger
75
+ self.class.logger
76
+ end
77
+
78
+ end
79
+ end
data/lib/roqs.rb ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'teLogger'
4
+ require 'toolrack'
5
+
6
+ require_relative "roqs/version"
7
+
8
+ module Roqs
9
+ include TR::CondUtils
10
+
11
+ # OQS_STATUS
12
+ OQS_ERROR = -1
13
+ OQS_SUCCESS = 0
14
+ OQS_EXTERNAL_LIB_ERROR_OPENSSL = 50
15
+
16
+ class Error < StandardError; end
17
+ # Your code goes here...
18
+
19
+ def self.logger(tag = nil, &block)
20
+ @_logger = TeLogger::Tlogger.new if @_logger.nil?
21
+
22
+ if block
23
+ if not_empty?(tag)
24
+ @_logger.with_tag(tag, &block)
25
+ else
26
+ @_logger.with_tag(@_logger.tag, &block)
27
+ end
28
+ elsif is_empty?(tag)
29
+ @_logger.tag = :roqs
30
+ @_logger
31
+ else
32
+ # no block but tag is given? hmm
33
+ @_logger.tag = tag
34
+ @_logger
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ require_relative "roqs/struct"
41
+ require_relative "roqs/kem"
42
+ require_relative "roqs/sig"
Binary file
Binary file
data/sig/roqs.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Roqs
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roqs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-11-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: teLogger
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: toolrack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.23'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.23'
41
+ - !ruby/object:Gem::Dependency
42
+ name: release-gem
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.3.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.3.3
55
+ description: ''
56
+ email:
57
+ - chris@antrapol.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".rspec"
63
+ - ".rubocop.yml"
64
+ - README.md
65
+ - Rakefile
66
+ - TEST-RESULT.md
67
+ - lib/roqs.rb
68
+ - lib/roqs/common_wrapper.rb
69
+ - lib/roqs/kem.rb
70
+ - lib/roqs/kem_public_key.rb
71
+ - lib/roqs/kem_wrapper.rb
72
+ - lib/roqs/sig.rb
73
+ - lib/roqs/sig_wrapper.rb
74
+ - lib/roqs/struct.rb
75
+ - lib/roqs/version.rb
76
+ - lib/roqs/wrapper.rb
77
+ - native/linux/x86_64/liboqs.so.0.9.0
78
+ - native/macos/x86_64/liboqs.0.7.0.dylib
79
+ - native/windows/x64/liboqs.dll
80
+ - sig/roqs.rbs
81
+ homepage: ''
82
+ licenses: []
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 2.6.0
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubygems_version: 3.4.6
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: ''
103
+ test_files: []