confium 0.3.2 → 0.3.4
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 +4 -4
- data/CHANGELOG.md +61 -0
- data/README.adoc +13 -5
- data/confium.gemspec +0 -1
- data/ext/confium_native/src/attributes.rs +5 -5
- data/ext/confium_native/src/audit.rs +8 -8
- data/ext/confium_native/src/composite.rs +10 -14
- data/ext/confium_native/src/deployment.rs +10 -9
- data/ext/confium_native/src/ers.rs +7 -11
- data/ext/confium_native/src/openpgp.rs +3 -3
- data/ext/confium_native/src/path.rs +8 -8
- data/ext/confium_native/src/pki.rs +34 -38
- data/ext/confium_native/src/tc.rs +27 -59
- data/ext/confium_native/src/transparency.rs +20 -61
- data/ext/confium_native/src/util.rs +45 -11
- data/lib/confium/audit.rb +1 -0
- data/lib/confium/composite.rb +50 -0
- data/lib/confium/crypto.rb +1 -0
- data/lib/confium/pki/cms/signed_data_builder.rb +4 -1
- data/lib/confium/pki.rb +2 -0
- data/lib/confium/transparency.rb +12 -0
- data/lib/confium/version.rb +1 -1
- data/lib/confium.rb +14 -3
- metadata +4 -16
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
//! DRY consolidation: a single `bytes_from_value` + size cap + string
|
|
4
4
|
//! conversion + typed-error helper shared by every subsystem module
|
|
5
5
|
//! (composite, pki, tc, transparency, deployment, attributes).
|
|
6
|
+
//!
|
|
7
|
+
//! This module wraps magnus's deprecated `exception::*` constructors
|
|
8
|
+
//! so the rest of the crate never touches them; their replacements
|
|
9
|
+
//! need a `Ruby` handle, which the failure fallbacks here lack.
|
|
10
|
+
#![allow(deprecated)]
|
|
6
11
|
|
|
7
12
|
use magnus::prelude::*;
|
|
8
13
|
use magnus::{exception, Error, RHash, RString, Ruby, TryConvert, Value};
|
|
@@ -14,6 +19,28 @@ use magnus::{exception, Error, RHash, RString, Ruby, TryConvert, Value};
|
|
|
14
19
|
/// prevent trivial memory-exhaustion attacks.
|
|
15
20
|
pub const MAX_INPUT_SIZE: usize = 1 << 20;
|
|
16
21
|
|
|
22
|
+
/// Build a plain `RuntimeError`. Centralizes every raise site so the
|
|
23
|
+
/// deprecated `magnus::exception::runtime_error()` fallback lives in
|
|
24
|
+
/// exactly one place (its replacement needs a `Ruby` handle, which is
|
|
25
|
+
/// unavailable when `Ruby::get()` itself fails).
|
|
26
|
+
pub fn runtime(msg: impl Into<String>) -> Error {
|
|
27
|
+
let msg: String = msg.into();
|
|
28
|
+
match Ruby::get() {
|
|
29
|
+
Ok(ruby) => Error::new(ruby.exception_runtime_error(), msg),
|
|
30
|
+
Err(_) => Error::new(exception::runtime_error(), msg),
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Build an `ArgumentError` — for bad argument shapes/ranges, the
|
|
35
|
+
/// class callers should see before any Confium semantics apply.
|
|
36
|
+
pub fn arg_error(msg: impl Into<String>) -> Error {
|
|
37
|
+
let msg: String = msg.into();
|
|
38
|
+
match Ruby::get() {
|
|
39
|
+
Ok(ruby) => Error::new(ruby.exception_arg_error(), msg),
|
|
40
|
+
Err(_) => Error::new(exception::arg_error(), msg),
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
17
44
|
/// Convert a Ruby value to bytes. Accepts a binary `String` (any
|
|
18
45
|
/// encoding) or an `Array<Integer>`. Enforces a 1 MiB size cap.
|
|
19
46
|
pub fn bytes_from_value(v: Value) -> Result<Vec<u8>, Error> {
|
|
@@ -30,10 +57,7 @@ pub fn bytes_from_value(v: Value) -> Result<Vec<u8>, Error> {
|
|
|
30
57
|
arr.into_iter()
|
|
31
58
|
.map(|i| {
|
|
32
59
|
if !(0..=255).contains(&i) {
|
|
33
|
-
Err(
|
|
34
|
-
exception::arg_error(),
|
|
35
|
-
format!("byte out of range 0..255: {i}"),
|
|
36
|
-
))
|
|
60
|
+
Err(arg_error(format!("byte out of range 0..255: {i}")))
|
|
37
61
|
} else {
|
|
38
62
|
Ok(i as u8)
|
|
39
63
|
}
|
|
@@ -46,18 +70,15 @@ pub fn bytes_from_value(v: Value) -> Result<Vec<u8>, Error> {
|
|
|
46
70
|
/// memory-exhaustion attacks.
|
|
47
71
|
pub fn enforce_size(len: usize) -> Result<(), Error> {
|
|
48
72
|
if len > MAX_INPUT_SIZE {
|
|
49
|
-
return Err(
|
|
50
|
-
exception::arg_error(),
|
|
51
|
-
format!("input size {0} exceeds max {MAX_INPUT_SIZE}", len),
|
|
52
|
-
));
|
|
73
|
+
return Err(arg_error(format!("input size {0} exceeds max {MAX_INPUT_SIZE}", len)));
|
|
53
74
|
}
|
|
54
75
|
Ok(())
|
|
55
76
|
}
|
|
56
77
|
|
|
57
78
|
/// Build a Ruby binary `String` from a byte slice. Avoids the UTF-8
|
|
58
|
-
/// round-trip
|
|
59
|
-
pub fn bytes_to_rstring(
|
|
60
|
-
let s =
|
|
79
|
+
/// round-trip for already-binary input.
|
|
80
|
+
pub fn bytes_to_rstring(ruby: &Ruby, bytes: &[u8]) -> RString {
|
|
81
|
+
let s = ruby.str_buf_new(0);
|
|
61
82
|
s.cat(bytes);
|
|
62
83
|
s
|
|
63
84
|
}
|
|
@@ -148,6 +169,19 @@ pub fn parse_error(msg: impl Into<String>, operation: &str, format: Option<&str>
|
|
|
148
169
|
confium_error(msg, "ParseError", d)
|
|
149
170
|
}
|
|
150
171
|
|
|
172
|
+
#[allow(dead_code)]
|
|
173
|
+
pub fn index_error(msg: impl Into<String>, operation: &str, index: Option<u64>) -> Error {
|
|
174
|
+
let ruby = match Ruby::get() {
|
|
175
|
+
Ok(r) => r,
|
|
176
|
+
Err(_) => return Error::new(exception::runtime_error(), msg.into()),
|
|
177
|
+
};
|
|
178
|
+
let d = new_details(&ruby);
|
|
179
|
+
let _ = d.aset("operation", operation);
|
|
180
|
+
let _ = d.aset("component", "Confium");
|
|
181
|
+
if let Some(i) = index { let _ = d.aset("index", i); }
|
|
182
|
+
confium_error(msg, "IndexError", d)
|
|
183
|
+
}
|
|
184
|
+
|
|
151
185
|
#[allow(dead_code)]
|
|
152
186
|
pub fn validation_error(msg: impl Into<String>, operation: &str, param: &str, expected: &str, actual: &str) -> Error {
|
|
153
187
|
let ruby = match Ruby::get() {
|
data/lib/confium/audit.rb
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Confium
|
|
6
|
+
module Composite
|
|
7
|
+
# JSON transport for composite signatures. The native extension
|
|
8
|
+
# defines Signature with algorithms/component_count/verify over
|
|
9
|
+
# component Hashes (algorithm, public_key, signature) whose
|
|
10
|
+
# binary fields cannot ride JSON directly, so the wire format
|
|
11
|
+
# hex-encodes them:
|
|
12
|
+
#
|
|
13
|
+
# json = Confium::Composite::Signature.components_to_json(components)
|
|
14
|
+
# sig = Confium::Composite::Signature.from_json(json)
|
|
15
|
+
# sig.verify(message)
|
|
16
|
+
class Signature
|
|
17
|
+
BINARY_FIELDS = %w[public_key signature].freeze
|
|
18
|
+
|
|
19
|
+
def self.components_to_json(components)
|
|
20
|
+
JSON.generate(components.map do |component|
|
|
21
|
+
component.transform_values do |value|
|
|
22
|
+
value.encoding == Encoding::ASCII_8BIT ? value.unpack1('H*') : value
|
|
23
|
+
end
|
|
24
|
+
end)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Accepts either a bare JSON array of component Hashes or a
|
|
28
|
+
# {"components": [...]} envelope, with public_key/signature
|
|
29
|
+
# hex-encoded on the wire. Takes a JSON string or an
|
|
30
|
+
# already-parsed Array/Hash.
|
|
31
|
+
def self.from_json(json)
|
|
32
|
+
data = json.is_a?(String) ? JSON.parse(json) : json
|
|
33
|
+
components = data.is_a?(Hash) ? data['components'] : data
|
|
34
|
+
unless components.is_a?(Array) && !components.empty?
|
|
35
|
+
raise ArgumentError, 'expected a non-empty "components" array'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
new(components.map { |c| decode_binary_fields(c) })
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.decode_binary_fields(component)
|
|
42
|
+
BINARY_FIELDS.each_with_object(component.dup) do |field, decoded|
|
|
43
|
+
value = component.fetch(field)
|
|
44
|
+
decoded[field] = [value].pack('H*') if value.is_a?(String)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
private_class_method :decode_binary_fields
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/confium/crypto.rb
CHANGED
|
@@ -33,6 +33,7 @@ module Confium
|
|
|
33
33
|
|
|
34
34
|
def initialize
|
|
35
35
|
@content = nil
|
|
36
|
+
# @type ivar @signers: Array[Hash[Symbol, untyped]]
|
|
36
37
|
@signers = []
|
|
37
38
|
end
|
|
38
39
|
|
|
@@ -81,7 +82,9 @@ module Confium
|
|
|
81
82
|
result.fetch('signature')
|
|
82
83
|
when :ecdsa_p256
|
|
83
84
|
result = Confium::TC::FrostP256.sign(private_key, payload)
|
|
84
|
-
|
|
85
|
+
# CMS carries ECDSA signatures DER-encoded (DSA-Sig-Value);
|
|
86
|
+
# FrostP256.sign returns { "der" => ..., "fixed" => ... }.
|
|
87
|
+
result.fetch('der')
|
|
85
88
|
else
|
|
86
89
|
raise ArgumentError, "unsupported algorithm: #{algorithm.inspect}"
|
|
87
90
|
end
|
data/lib/confium/pki.rb
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Confium::Transparency namespace file.
|
|
4
|
+
#
|
|
5
|
+
# The Transparency module itself is defined by the native Rust
|
|
6
|
+
# extension via magnus at require time. This file registers
|
|
7
|
+
# pure-Ruby autoloads for the Transparency submodules.
|
|
8
|
+
module Confium
|
|
9
|
+
module Transparency
|
|
10
|
+
autoload :OTS, 'confium/transparency/ots'
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/confium/version.rb
CHANGED
data/lib/confium.rb
CHANGED
|
@@ -18,8 +18,7 @@ begin
|
|
|
18
18
|
# 3.1 and 3.2 get exact-minor builds while 3.3 covers 3.3+).
|
|
19
19
|
# Source builds install the extension flat, without a version
|
|
20
20
|
# directory.
|
|
21
|
-
|
|
22
|
-
window = major > 3 || minor >= 3 ? '3.3' : "#{major}.#{minor}"
|
|
21
|
+
window = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3') ? '3.3' : RUBY_VERSION[/\A\d+\.\d+/]
|
|
23
22
|
begin
|
|
24
23
|
require_relative "confium_native/#{window}/confium_native"
|
|
25
24
|
rescue LoadError
|
|
@@ -56,9 +55,21 @@ module Confium
|
|
|
56
55
|
autoload :PolicyViolationError, 'confium/errors/policy_violation_error'
|
|
57
56
|
autoload :SecureBytes, 'confium/secure_bytes'
|
|
58
57
|
autoload :Policy, 'confium/policy'
|
|
59
|
-
|
|
58
|
+
# PKI is native-defined, so an autoload would never fire; the
|
|
59
|
+
# namespace file is eager-required and registers the pure-Ruby
|
|
60
|
+
# submodules (CMS, CertificateBuilder, CNML) as autoloads.
|
|
61
|
+
require_relative 'confium/pki'
|
|
60
62
|
end
|
|
61
63
|
|
|
64
|
+
# Eager-load the Composite Signature JSON companion. The native
|
|
65
|
+
# extension defines Confium::Composite; this file reopens the class
|
|
66
|
+
# to add from_json transport.
|
|
67
|
+
require_relative 'confium/composite'
|
|
68
|
+
|
|
69
|
+
# Eager-load the Transparency namespace for the OTS autoload (the
|
|
70
|
+
# module itself is native-defined).
|
|
71
|
+
require_relative 'confium/transparency'
|
|
72
|
+
|
|
62
73
|
# Eager-load the Audit Ruby companion. The native extension registers
|
|
63
74
|
# `Confium::Audit` as a Ruby module with the `record`/`sink=`/`sink`
|
|
64
75
|
# methods; the companion file defines the Sink class hierarchy on top
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: confium
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Open
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rb_sys
|
|
@@ -52,20 +52,6 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: 1.3.0
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: rake-compiler-dock
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '1.3'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '1.3'
|
|
69
55
|
- !ruby/object:Gem::Dependency
|
|
70
56
|
name: rspec
|
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -144,6 +130,7 @@ files:
|
|
|
144
130
|
- lib/confium.rb
|
|
145
131
|
- lib/confium/audit.rb
|
|
146
132
|
- lib/confium/cfm.rb
|
|
133
|
+
- lib/confium/composite.rb
|
|
147
134
|
- lib/confium/crypto.rb
|
|
148
135
|
- lib/confium/digest.rb
|
|
149
136
|
- lib/confium/errors.rb
|
|
@@ -172,6 +159,7 @@ files:
|
|
|
172
159
|
- lib/confium/tc/session.rb
|
|
173
160
|
- lib/confium/tc/session_stub.rb
|
|
174
161
|
- lib/confium/tc/share_file.rb
|
|
162
|
+
- lib/confium/transparency.rb
|
|
175
163
|
- lib/confium/transparency/ots.rb
|
|
176
164
|
- lib/confium/version.rb
|
|
177
165
|
homepage: https://www.confium.org
|