roqs 0.1.0

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 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: []