Module: PQCrypto::PKCS8
- Defined in:
- lib/pq_crypto/pkcs8.rb
Constant Summary collapse
- PEM_LABEL =
"PRIVATE KEY"- PEM_BEGIN =
"-----BEGIN #{PEM_LABEL}-----"- PEM_END =
"-----END #{PEM_LABEL}-----"- ML_KEM_SEED_BYTES =
64- ML_DSA_SEED_BYTES =
32- PRIVATE_KEY_CHOICES =
{ ml_kem_512: { seed_bytes: ML_KEM_SEED_BYTES, expanded_bytes: PQCrypto::ML_KEM_512_SECRET_KEY_BYTES, supported_formats: %i[seed expanded both], }.freeze, ml_kem_768: { seed_bytes: ML_KEM_SEED_BYTES, expanded_bytes: PQCrypto::ML_KEM_SECRET_KEY_BYTES, supported_formats: %i[seed expanded both], }.freeze, ml_kem_1024: { seed_bytes: ML_KEM_SEED_BYTES, expanded_bytes: PQCrypto::ML_KEM_1024_SECRET_KEY_BYTES, supported_formats: %i[seed expanded both], }.freeze, ml_dsa_44: { seed_bytes: ML_DSA_SEED_BYTES, expanded_bytes: PQCrypto::SIGN_44_SECRET_KEY_BYTES, supported_formats: %i[seed expanded both], }.freeze, ml_dsa_65: { seed_bytes: ML_DSA_SEED_BYTES, expanded_bytes: PQCrypto::SIGN_SECRET_KEY_BYTES, supported_formats: %i[seed expanded both], }.freeze, ml_dsa_87: { seed_bytes: ML_DSA_SEED_BYTES, expanded_bytes: PQCrypto::SIGN_87_SECRET_KEY_BYTES, supported_formats: %i[seed expanded both], }.freeze, }.freeze
Class Attribute Summary collapse
-
.allow_ml_dsa_seed_format ⇒ Object
Returns the value of attribute allow_ml_dsa_seed_format.
Class Method Summary collapse
- .decode_der(der) ⇒ Object
- .decode_pem(pem) ⇒ Object
- .encode_der(algorithm_symbol, secret_material, format:) ⇒ Object
- .encode_pem(algorithm_symbol, secret_material, format:) ⇒ Object
Class Attribute Details
.allow_ml_dsa_seed_format ⇒ Object
Returns the value of attribute allow_ml_dsa_seed_format.
49 50 51 |
# File 'lib/pq_crypto/pkcs8.rb', line 49 def allow_ml_dsa_seed_format @allow_ml_dsa_seed_format end |
Class Method Details
.decode_der(der) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/pq_crypto/pkcs8.rb', line 84 def decode_der(der) input = String(der).b outer = decode_asn1(input) raise SerializationError, "PKCS#8 DER contains trailing data" unless outer.to_der.b == input raise SerializationError, "PKCS#8 must be an ASN.1 SEQUENCE" unless outer.is_a?(OpenSSL::ASN1::Sequence) raise SerializationError, "PKCS#8 OneAsymmetricKey must contain exactly 3 elements" unless outer.value.size == 3 version, algorithm_identifier, private_key = outer.value decode_version(version) algorithm = decode_algorithm_identifier(algorithm_identifier) entry = AlgorithmRegistry.fetch(algorithm) validate_secret_key_algorithm!(algorithm, entry) unless private_key.is_a?(OpenSSL::ASN1::OctetString) raise SerializationError, "PKCS#8 privateKey must be an OCTET STRING" end decode_private_key_choice(algorithm, String(private_key.value).b) end |
.decode_pem(pem) ⇒ Object
104 105 106 107 |
# File 'lib/pq_crypto/pkcs8.rb', line 104 def decode_pem(pem) der = der_from_pem(pem) decode_der(der) end |
.encode_der(algorithm_symbol, secret_material, format:) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/pq_crypto/pkcs8.rb', line 51 def encode_der(algorithm_symbol, secret_material, format:) entry = AlgorithmRegistry.fetch(algorithm_symbol) validate_secret_key_algorithm!(algorithm_symbol, entry) ensure_format_supported!(algorithm_symbol, format) choice_der = case format when :seed encode_seed_choice(secret_material, algorithm_symbol) when :expanded (secret_material, algorithm_symbol) when :both encode_both_choice(secret_material, algorithm_symbol) else raise SerializationError, "Unsupported PKCS#8 private key format: #{format.inspect}" end OpenSSL::ASN1::Sequence.new([ OpenSSL::ASN1::Integer.new(0), OpenSSL::ASN1::Sequence.new([ OpenSSL::ASN1::ObjectId.new(AlgorithmRegistry.standard_oid(algorithm_symbol)), ]), OpenSSL::ASN1::OctetString.new(choice_der), ]).to_der.b rescue OpenSSL::ASN1::ASN1Error => e raise SerializationError, e. end |
.encode_pem(algorithm_symbol, secret_material, format:) ⇒ Object
78 79 80 81 82 |
# File 'lib/pq_crypto/pkcs8.rb', line 78 def encode_pem(algorithm_symbol, secret_material, format:) der = encode_der(algorithm_symbol, secret_material, format: format) body = encode_base64(der).scan(/.{1,64}/).join("\n") "#{PEM_BEGIN}\n#{body}\n#{PEM_END}\n" end |