Class: JWT::PQ::MlDsa Private
- Inherits:
-
Object
- Object
- JWT::PQ::MlDsa
- Defined in:
- lib/jwt/pq/ml_dsa.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Ruby wrapper around liboqs ML-DSA operations. Handles memory allocation, FFI calls, and cleanup.
Constant Summary collapse
- ALGORITHMS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
{ "ML-DSA-44" => { public_key: 1312, secret_key: 2560, signature: 2420, nist_level: 2 }, "ML-DSA-65" => { public_key: 1952, secret_key: 4032, signature: 3309, nist_level: 3 }, "ML-DSA-87" => { public_key: 2592, secret_key: 4896, signature: 4627, nist_level: 5 } }.freeze
Instance Attribute Summary collapse
- #algorithm ⇒ Object readonly private
Class Method Summary collapse
-
.reset_handles! ⇒ void
private
Drop the process-wide cache of
OQS_SIGhandles. - .sign_handle(algorithm) ⇒ Object private
- .verify_handle(algorithm) ⇒ Object private
Instance Method Summary collapse
-
#initialize(algorithm) ⇒ MlDsa
constructor
private
A new instance of MlDsa.
-
#keypair ⇒ Object
private
Generate a new keypair.
-
#public_key_size ⇒ Object
private
Key sizes for this algorithm.
- #secret_key_size ⇒ Object private
-
#sign(message, secret_key) ⇒ Object
private
Sign a message with a secret key.
-
#sign_with_sk_buffer(message, sk_buf) ⇒ Object
private
Faster sign path: takes a pre-populated FFI::MemoryPointer holding the secret key.
- #signature_size ⇒ Object private
-
#verify(message, signature, public_key) ⇒ Object
private
Verify a signature against a message and public key.
-
#verify_with_pk_buffer(message, signature, pk_buf) ⇒ Object
private
Faster verify path: takes a pre-populated FFI::MemoryPointer holding the public key.
Constructor Details
#initialize(algorithm) ⇒ MlDsa
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of MlDsa.
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/jwt/pq/ml_dsa.rb', line 65 def initialize(algorithm) algorithm = algorithm.to_s unless ALGORITHMS.key?(algorithm) raise UnsupportedAlgorithmError, "Unsupported algorithm: #{algorithm}. " \ "Supported: #{ALGORITHMS.keys.join(", ")}" end @algorithm = algorithm @sizes = ALGORITHMS[algorithm] end |
Instance Attribute Details
#algorithm ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
63 64 65 |
# File 'lib/jwt/pq/ml_dsa.rb', line 63 def algorithm @algorithm end |
Class Method Details
.reset_handles! ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Drop the process-wide cache of OQS_SIG handles.
The first call to sign_handle or verify_handle in a process
(or after this reset) lazily allocates a fresh handle. The
inherited handles in the child are not explicitly freed — doing
so can confuse malloc bookkeeping across forked processes. The
handles leak until process exit (≤3 algorithms × <1 KB each),
which is negligible.
Prefer the public JWT::PQ.reset_handles! wrapper from application code.
58 59 60 61 |
# File 'lib/jwt/pq/ml_dsa.rb', line 58 def self.reset_handles! @sign_handles_mutex.synchronize { @sign_handles.clear } @verify_handles_mutex.synchronize { @verify_handles.clear } end |
.sign_handle(algorithm) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/jwt/pq/ml_dsa.rb', line 19 def self.sign_handle(algorithm) @sign_handles_mutex.synchronize do @sign_handles[algorithm] ||= begin h = LibOQS.OQS_SIG_new(algorithm) raise LiboqsError, "Failed to initialize #{algorithm}" if h.null? h end end end |
.verify_handle(algorithm) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/jwt/pq/ml_dsa.rb', line 33 def self.verify_handle(algorithm) @verify_handles_mutex.synchronize do @verify_handles[algorithm] ||= begin h = LibOQS.OQS_SIG_new(algorithm) raise LiboqsError, "Failed to initialize #{algorithm}" if h.null? h end end end |
Instance Method Details
#keypair ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Generate a new keypair. Returns [public_key_bytes, secret_key_bytes]
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/jwt/pq/ml_dsa.rb', line 79 def keypair sig = LibOQS.OQS_SIG_new(@algorithm) raise LiboqsError, "Failed to initialize #{@algorithm}" if sig.null? pk = FFI::MemoryPointer.new(:uint8, @sizes[:public_key]) sk = FFI::MemoryPointer.new(:uint8, @sizes[:secret_key]) status = LibOQS.OQS_SIG_keypair(sig, pk, sk) raise LiboqsError, "Keypair generation failed for #{@algorithm}" unless status == LibOQS::OQS_SUCCESS [pk.read_bytes(@sizes[:public_key]), sk.read_bytes(@sizes[:secret_key])] ensure sk&.clear LibOQS.OQS_SIG_free(sig) if sig && !sig.null? end |
#public_key_size ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Key sizes for this algorithm
150 151 152 |
# File 'lib/jwt/pq/ml_dsa.rb', line 150 def public_key_size @sizes[:public_key] end |
#secret_key_size ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
154 155 156 |
# File 'lib/jwt/pq/ml_dsa.rb', line 154 def secret_key_size @sizes[:secret_key] end |
#sign(message, secret_key) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Sign a message with a secret key. Returns the signature bytes.
97 98 99 100 101 102 103 104 105 |
# File 'lib/jwt/pq/ml_dsa.rb', line 97 def sign(, secret_key) validate_key_size!(secret_key, :secret_key) sk_buf = FFI::MemoryPointer.new(:uint8, secret_key.bytesize) sk_buf.put_bytes(0, secret_key) sign_with_sk_buffer(, sk_buf) ensure sk_buf&.clear end |
#sign_with_sk_buffer(message, sk_buf) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Faster sign path: takes a pre-populated FFI::MemoryPointer holding the secret key. Caller is responsible for buffer lifecycle (allocation, zeroing). Used by JWT::PQ::Key to avoid re-allocating+copying the secret key on every sign call.
111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/jwt/pq/ml_dsa.rb', line 111 def sign_with_sk_buffer(, sk_buf) sig = self.class.sign_handle(@algorithm) sig_buf = FFI::MemoryPointer.new(:uint8, @sizes[:signature]) sig_len = FFI::MemoryPointer.new(:size_t) msg_buf = FFI::MemoryPointer.from_string() status = LibOQS.OQS_SIG_sign(sig, sig_buf, sig_len, msg_buf, .bytesize, sk_buf) raise SignatureError, "Signing failed for #{@algorithm}" unless status == LibOQS::OQS_SUCCESS sig_buf.read_bytes(sig_len.read(:size_t)) end |
#signature_size ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
158 159 160 |
# File 'lib/jwt/pq/ml_dsa.rb', line 158 def signature_size @sizes[:signature] end |
#verify(message, signature, public_key) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Verify a signature against a message and public key. Returns true if valid, false otherwise.
126 127 128 129 130 131 132 |
# File 'lib/jwt/pq/ml_dsa.rb', line 126 def verify(, signature, public_key) validate_key_size!(public_key, :public_key) pk_buf = FFI::MemoryPointer.new(:uint8, public_key.bytesize) pk_buf.put_bytes(0, public_key) verify_with_pk_buffer(, signature, pk_buf) end |
#verify_with_pk_buffer(message, signature, pk_buf) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Faster verify path: takes a pre-populated FFI::MemoryPointer holding the public key. Caller is responsible for buffer lifecycle. Used by JWT::PQ::Key to avoid re-allocating+copying the public key on every verify call.
138 139 140 141 142 143 144 145 146 147 |
# File 'lib/jwt/pq/ml_dsa.rb', line 138 def verify_with_pk_buffer(, signature, pk_buf) sig = self.class.verify_handle(@algorithm) msg_buf = FFI::MemoryPointer.from_string() sig_buf = FFI::MemoryPointer.new(:uint8, signature.bytesize) sig_buf.put_bytes(0, signature) status = LibOQS.OQS_SIG_verify(sig, msg_buf, .bytesize, sig_buf, signature.bytesize, pk_buf) status == LibOQS::OQS_SUCCESS end |