Module: PQCrypto::PKCS8

Defined in:
lib/pq_crypto/pkcs8.rb,
lib/pq_crypto/pkcs8/der.rb,
lib/pq_crypto/pkcs8/private_key_choice.rb

Defined Under Namespace

Modules: DER, PrivateKeyChoice

Constant Summary collapse

PEM_LABEL =
"PRIVATE KEY"
PEM_BEGIN =
"-----BEGIN #{PEM_LABEL}-----"
PEM_END =
"-----END #{PEM_LABEL}-----"
ENCRYPTED_PEM_LABEL =
"ENCRYPTED PRIVATE KEY"
ENCRYPTED_PEM_BEGIN =
"-----BEGIN #{ENCRYPTED_PEM_LABEL}-----"
ENCRYPTED_PEM_END =
"-----END #{ENCRYPTED_PEM_LABEL}-----"
ML_KEM_SEED_BYTES =
64
ML_DSA_SEED_BYTES =
32
ENCRYPTED_PKCS8_DEFAULT_ITERATIONS =
200_000
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

Class Method Summary collapse

Class Attribute Details

.allow_ml_dsa_seed_formatObject

Returns the value of attribute allow_ml_dsa_seed_format.



51
52
53
# File 'lib/pq_crypto/pkcs8.rb', line 51

def allow_ml_dsa_seed_format
  @allow_ml_dsa_seed_format
end

Class Method Details

.decode_der(der, passphrase: nil) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/pq_crypto/pkcs8.rb', line 74

def decode_der(der, passphrase: nil)
  input = Internal.binary_string(der)
  return decode_encrypted_der(input, passphrase: passphrase) if encrypted_der?(input)

  oid, choice_der = private_key_info_from_der(input)
  algorithm = AlgorithmRegistry.by_standard_oid(oid)
  raise SerializationError, "Unsupported PKCS#8 algorithm OID: #{oid}" if algorithm.nil?

  entry = AlgorithmRegistry.fetch(algorithm)
  PrivateKeyChoice.validate_secret_key_algorithm!(algorithm, entry)
  PrivateKeyChoice.decode(algorithm, Internal.binary_string(choice_der))
rescue ArgumentError => e
  raise SerializationError, e.message
ensure
  Internal.safe_wipe(choice_der) if defined?(choice_der)
end

.decode_pem(pem, passphrase: nil) ⇒ Object



91
92
93
94
95
96
97
98
# File 'lib/pq_crypto/pkcs8.rb', line 91

def decode_pem(pem, passphrase: nil)
  _encrypted, der = pkcs8_native { PQCrypto.__send__(:native_pkcs8_pem_to_der, String(pem)) }
  begin
    decode_der(der, passphrase: passphrase)
  ensure
    Internal.safe_wipe(der)
  end
end

.encode_der(algorithm, secret_material, format:, passphrase: nil, iterations: ENCRYPTED_PKCS8_DEFAULT_ITERATIONS) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/pq_crypto/pkcs8.rb', line 53

def encode_der(algorithm, secret_material, format:, passphrase: nil, iterations: ENCRYPTED_PKCS8_DEFAULT_ITERATIONS)
  entry = AlgorithmRegistry.fetch(algorithm)
  PrivateKeyChoice.validate_secret_key_algorithm!(algorithm, entry)

  choice_der = PrivateKeyChoice.encode(algorithm, secret_material, format)
  der = private_key_info_to_der(algorithm, choice_der)
  return der if passphrase.nil?

  encrypt_der(der, passphrase: passphrase, iterations: iterations)
rescue ArgumentError => e
  raise SerializationError, e.message
ensure
  Internal.safe_wipe(choice_der) if defined?(choice_der)
  Internal.safe_wipe(der) if passphrase && defined?(der)
end

.encode_pem(algorithm, secret_material, format:, passphrase: nil, iterations: ENCRYPTED_PKCS8_DEFAULT_ITERATIONS) ⇒ Object



69
70
71
72
# File 'lib/pq_crypto/pkcs8.rb', line 69

def encode_pem(algorithm, secret_material, format:, passphrase: nil, iterations: ENCRYPTED_PKCS8_DEFAULT_ITERATIONS)
  der = encode_der(algorithm, secret_material, format: format, passphrase: passphrase, iterations: iterations)
  pkcs8_native { PQCrypto.__send__(:native_pkcs8_der_to_pem, der, !passphrase.nil?) }
end