pq_crypto 0.6.0 → 0.6.1
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 +7 -0
- data/ext/pqcrypto/extconf.rb +2 -0
- data/ext/pqcrypto/pqcrypto_ruby_secure.c +139 -0
- data/ext/pqcrypto/pqcrypto_secure.c +532 -0
- data/ext/pqcrypto/pqcrypto_secure.h +20 -0
- data/ext/pqcrypto/pqcrypto_version.h +1 -1
- data/lib/pq_crypto/hybrid_kem.rb +1 -1
- data/lib/pq_crypto/internal.rb +23 -0
- data/lib/pq_crypto/kem.rb +27 -34
- data/lib/pq_crypto/pkcs8/der.rb +68 -0
- data/lib/pq_crypto/pkcs8/private_key_choice.rb +186 -0
- data/lib/pq_crypto/pkcs8.rb +51 -468
- data/lib/pq_crypto/serialization.rb +19 -29
- data/lib/pq_crypto/signature.rb +28 -35
- data/lib/pq_crypto/version.rb +1 -1
- data/lib/pq_crypto.rb +10 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 78b11d409c22bfd37c2afcf11cfdeb8bc7e825a1e4ebf8b0a94c655afbd59f78
|
|
4
|
+
data.tar.gz: 0206a99c5b364c812176c3d31629e5eb1490dcf694a2c8902b9537fd1ab16ebc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d79069163427ae03428e5ff8d01af39315cef796d498f59ca8e021c92f6a987b6a1a6d04c8e6826529a85df1af428f80086dc1f56cda74b0866e16aca27b8901
|
|
7
|
+
data.tar.gz: 552eb1abce00c25fc1313690c5df3a4a341b158caa3aa3ec2e37b604499c43c514fd2e0b82b245961acc4e73895dcbc1b7637112958660a91e0a32b8e3e91134
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.1] - 2026-05-14
|
|
4
|
+
|
|
5
|
+
### Security
|
|
6
|
+
|
|
7
|
+
- Moved PKCS#8 PEM handling, PrivateKeyInfo wrapping/unwrapping, and encrypted PKCS#8 encryption/decryption to native C/OpenSSL helpers.
|
|
8
|
+
- Removed Ruby `OpenSSL::ASN1` parsing/building from the PKCS#8 path while preserving the existing Ruby API.
|
|
9
|
+
|
|
3
10
|
## [0.6.0] - 2026-05-14
|
|
4
11
|
|
|
5
12
|
### Added
|
data/ext/pqcrypto/extconf.rb
CHANGED
|
@@ -201,6 +201,8 @@ def configure_openssl!
|
|
|
201
201
|
abort "openssl/evp.h is required" unless have_header("openssl/evp.h")
|
|
202
202
|
abort "openssl/rand.h is required" unless have_header("openssl/rand.h")
|
|
203
203
|
abort "openssl/crypto.h is required" unless have_header("openssl/crypto.h")
|
|
204
|
+
abort "openssl/x509.h is required" unless have_header("openssl/x509.h")
|
|
205
|
+
abort "openssl/pkcs12.h is required" unless have_header("openssl/pkcs12.h")
|
|
204
206
|
|
|
205
207
|
version_check = <<~SRC
|
|
206
208
|
#include <openssl/opensslv.h>
|
|
@@ -1741,6 +1741,136 @@ static VALUE pqcrypto__native_mldsa_verify_mu(int argc, VALUE *argv, VALUE self)
|
|
|
1741
1741
|
pq_raise_general_error(call.result);
|
|
1742
1742
|
}
|
|
1743
1743
|
|
|
1744
|
+
static VALUE pqcrypto_pkcs8_private_key_info_to_der(VALUE self, VALUE oid_text, VALUE private_key) {
|
|
1745
|
+
(void)self;
|
|
1746
|
+
uint8_t *out = NULL;
|
|
1747
|
+
size_t out_len = 0;
|
|
1748
|
+
VALUE result;
|
|
1749
|
+
int ret;
|
|
1750
|
+
|
|
1751
|
+
StringValue(oid_text);
|
|
1752
|
+
StringValue(private_key);
|
|
1753
|
+
ret = pq_pkcs8_private_key_info_to_der(&out, &out_len, RSTRING_PTR(oid_text),
|
|
1754
|
+
(const uint8_t *)RSTRING_PTR(private_key),
|
|
1755
|
+
(size_t)RSTRING_LEN(private_key));
|
|
1756
|
+
if (ret != PQ_SUCCESS)
|
|
1757
|
+
pq_raise_general_error(ret);
|
|
1758
|
+
result = pq_string_from_buffer(out, out_len);
|
|
1759
|
+
pq_wipe_and_free(out, out_len);
|
|
1760
|
+
return result;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
static VALUE pqcrypto_pkcs8_private_key_info_from_der(VALUE self, VALUE der) {
|
|
1764
|
+
(void)self;
|
|
1765
|
+
char *oid_text = NULL;
|
|
1766
|
+
uint8_t *private_key = NULL;
|
|
1767
|
+
size_t private_key_len = 0;
|
|
1768
|
+
VALUE result;
|
|
1769
|
+
int ret;
|
|
1770
|
+
|
|
1771
|
+
StringValue(der);
|
|
1772
|
+
ret = pq_pkcs8_private_key_info_from_der(&oid_text, &private_key, &private_key_len,
|
|
1773
|
+
(const uint8_t *)RSTRING_PTR(der),
|
|
1774
|
+
(size_t)RSTRING_LEN(der));
|
|
1775
|
+
if (ret != PQ_SUCCESS)
|
|
1776
|
+
pq_raise_general_error(ret);
|
|
1777
|
+
|
|
1778
|
+
result = rb_ary_new_capa(2);
|
|
1779
|
+
rb_ary_push(result, rb_str_new_cstr(oid_text));
|
|
1780
|
+
rb_ary_push(result, pq_string_from_buffer(private_key, private_key_len));
|
|
1781
|
+
free(oid_text);
|
|
1782
|
+
pq_wipe_and_free(private_key, private_key_len);
|
|
1783
|
+
return result;
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
static VALUE pqcrypto_pkcs8_encrypt_der(VALUE self, VALUE der, VALUE passphrase,
|
|
1787
|
+
VALUE iterations_value) {
|
|
1788
|
+
(void)self;
|
|
1789
|
+
uint8_t *out = NULL;
|
|
1790
|
+
size_t out_len = 0;
|
|
1791
|
+
int iterations;
|
|
1792
|
+
VALUE result;
|
|
1793
|
+
int ret;
|
|
1794
|
+
|
|
1795
|
+
StringValue(der);
|
|
1796
|
+
StringValue(passphrase);
|
|
1797
|
+
iterations = NUM2INT(iterations_value);
|
|
1798
|
+
ret = pq_pkcs8_encrypt_private_key_info_der(&out, &out_len, (const uint8_t *)RSTRING_PTR(der),
|
|
1799
|
+
(size_t)RSTRING_LEN(der), RSTRING_PTR(passphrase),
|
|
1800
|
+
(size_t)RSTRING_LEN(passphrase), iterations);
|
|
1801
|
+
if (ret != PQ_SUCCESS)
|
|
1802
|
+
pq_raise_general_error(ret);
|
|
1803
|
+
result = pq_string_from_buffer(out, out_len);
|
|
1804
|
+
pq_wipe_and_free(out, out_len);
|
|
1805
|
+
return result;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
static VALUE pqcrypto_pkcs8_decrypt_der(VALUE self, VALUE der, VALUE passphrase) {
|
|
1809
|
+
(void)self;
|
|
1810
|
+
uint8_t *out = NULL;
|
|
1811
|
+
size_t out_len = 0;
|
|
1812
|
+
VALUE result;
|
|
1813
|
+
int ret;
|
|
1814
|
+
|
|
1815
|
+
StringValue(der);
|
|
1816
|
+
StringValue(passphrase);
|
|
1817
|
+
ret = pq_pkcs8_decrypt_private_key_info_der(&out, &out_len, (const uint8_t *)RSTRING_PTR(der),
|
|
1818
|
+
(size_t)RSTRING_LEN(der), RSTRING_PTR(passphrase),
|
|
1819
|
+
(size_t)RSTRING_LEN(passphrase));
|
|
1820
|
+
if (ret != PQ_SUCCESS)
|
|
1821
|
+
pq_raise_general_error(ret);
|
|
1822
|
+
result = pq_string_from_buffer(out, out_len);
|
|
1823
|
+
pq_wipe_and_free(out, out_len);
|
|
1824
|
+
return result;
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
static VALUE pqcrypto_pkcs8_encrypted_der_p(VALUE self, VALUE der) {
|
|
1828
|
+
(void)self;
|
|
1829
|
+
StringValue(der);
|
|
1830
|
+
return pq_pkcs8_der_is_encrypted_private_key_info((const uint8_t *)RSTRING_PTR(der),
|
|
1831
|
+
(size_t)RSTRING_LEN(der))
|
|
1832
|
+
? Qtrue
|
|
1833
|
+
: Qfalse;
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
static VALUE pqcrypto_pkcs8_der_to_pem(VALUE self, VALUE der, VALUE encrypted_value) {
|
|
1837
|
+
(void)self;
|
|
1838
|
+
char *pem = NULL;
|
|
1839
|
+
size_t pem_len = 0;
|
|
1840
|
+
VALUE result;
|
|
1841
|
+
int ret;
|
|
1842
|
+
|
|
1843
|
+
StringValue(der);
|
|
1844
|
+
ret = pq_pkcs8_der_to_pem(&pem, &pem_len, (const uint8_t *)RSTRING_PTR(der),
|
|
1845
|
+
(size_t)RSTRING_LEN(der), RTEST(encrypted_value) ? 1 : 0);
|
|
1846
|
+
if (ret != PQ_SUCCESS)
|
|
1847
|
+
pq_raise_general_error(ret);
|
|
1848
|
+
result = rb_str_new(pem, (long)pem_len);
|
|
1849
|
+
pq_secure_wipe(pem, pem_len);
|
|
1850
|
+
free(pem);
|
|
1851
|
+
return result;
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
static VALUE pqcrypto_pkcs8_pem_to_der(VALUE self, VALUE pem) {
|
|
1855
|
+
(void)self;
|
|
1856
|
+
uint8_t *der = NULL;
|
|
1857
|
+
size_t der_len = 0;
|
|
1858
|
+
int encrypted = 0;
|
|
1859
|
+
VALUE result;
|
|
1860
|
+
int ret;
|
|
1861
|
+
|
|
1862
|
+
StringValue(pem);
|
|
1863
|
+
ret =
|
|
1864
|
+
pq_pkcs8_pem_to_der(&der, &der_len, &encrypted, RSTRING_PTR(pem), (size_t)RSTRING_LEN(pem));
|
|
1865
|
+
if (ret != PQ_SUCCESS)
|
|
1866
|
+
pq_raise_general_error(ret);
|
|
1867
|
+
result = rb_ary_new_capa(2);
|
|
1868
|
+
rb_ary_push(result, encrypted ? Qtrue : Qfalse);
|
|
1869
|
+
rb_ary_push(result, pq_string_from_buffer(der, der_len));
|
|
1870
|
+
pq_wipe_and_free(der, der_len);
|
|
1871
|
+
return result;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1744
1874
|
static void define_constants(void) {
|
|
1745
1875
|
rb_define_const(mPQCrypto, "ML_KEM_512_PUBLIC_KEY_BYTES", INT2NUM(MLKEM512_PUBLICKEYBYTES));
|
|
1746
1876
|
rb_define_const(mPQCrypto, "ML_KEM_512_SECRET_KEY_BYTES", INT2NUM(MLKEM512_SECRETKEYBYTES));
|
|
@@ -1911,6 +2041,15 @@ void Init_pqcrypto_secure(void) {
|
|
|
1911
2041
|
pqcrypto_secret_key_from_pqc_container_der, 1);
|
|
1912
2042
|
rb_define_module_function(mPQCrypto, "secret_key_from_pqc_container_pem",
|
|
1913
2043
|
pqcrypto_secret_key_from_pqc_container_pem, 1);
|
|
2044
|
+
rb_define_module_function(mPQCrypto, "pkcs8_private_key_info_to_der",
|
|
2045
|
+
pqcrypto_pkcs8_private_key_info_to_der, 2);
|
|
2046
|
+
rb_define_module_function(mPQCrypto, "pkcs8_private_key_info_from_der",
|
|
2047
|
+
pqcrypto_pkcs8_private_key_info_from_der, 1);
|
|
2048
|
+
rb_define_module_function(mPQCrypto, "pkcs8_encrypt_der", pqcrypto_pkcs8_encrypt_der, 3);
|
|
2049
|
+
rb_define_module_function(mPQCrypto, "pkcs8_decrypt_der", pqcrypto_pkcs8_decrypt_der, 2);
|
|
2050
|
+
rb_define_module_function(mPQCrypto, "pkcs8_encrypted_der?", pqcrypto_pkcs8_encrypted_der_p, 1);
|
|
2051
|
+
rb_define_module_function(mPQCrypto, "pkcs8_der_to_pem", pqcrypto_pkcs8_der_to_pem, 2);
|
|
2052
|
+
rb_define_module_function(mPQCrypto, "pkcs8_pem_to_der", pqcrypto_pkcs8_pem_to_der, 1);
|
|
1914
2053
|
rb_define_module_function(mPQCrypto, "_native_mldsa_extract_tr",
|
|
1915
2054
|
pqcrypto__native_mldsa_extract_tr, -1);
|
|
1916
2055
|
rb_define_module_function(mPQCrypto, "_native_mldsa_compute_tr",
|