lib/cose/key/rsa.rb in cose-0.5.0 vs lib/cose/key/rsa.rb in cose-0.6.0

- old
+ new

@@ -9,102 +9,127 @@ LABEL_N = -1 LABEL_E = -2 LABEL_D = -3 LABEL_P = -4 LABEL_Q = -5 - LABEL_D_P = -6 - LABEL_D_Q = -7 - LABEL_Q_INV = -8 + LABEL_DP = -6 + LABEL_DQ = -7 + LABEL_QINV = -8 KTY_RSA = 3 + def self.enforce_type(map) + if map[LABEL_KTY] != KTY_RSA + raise "Not an RSA key" + end + end + def self.from_pkey(pkey) params = pkey.params attributes = { - modulus_n: params["n"].to_s(2), - public_exponent_e: params["e"].to_s(2) + n: params["n"].to_s(2), + e: params["e"].to_s(2) } if pkey.private? attributes.merge!( - private_exponent_d: params["d"].to_s(2), - prime_factor_p: params["p"].to_s(2), - prime_factor_q: params["q"].to_s(2), - d_p: params["dmp1"].to_s(2), - d_q: params["dmq1"].to_s(2), - q_inv: params["iqmp"].to_s(2) + d: params["d"].to_s(2), + p: params["p"].to_s(2), + q: params["q"].to_s(2), + dp: params["dmp1"].to_s(2), + dq: params["dmq1"].to_s(2), + qinv: params["iqmp"].to_s(2) ) end new(attributes) end - attr_reader( - :modulus_n, - :public_exponent_e, - :private_exponent_d, - :prime_factor_p, - :prime_factor_q, - :d_p, - :d_q, - :q_inv - ) + attr_reader :n, :e, :d, :p, :q, :dp, :dq, :qinv - def initialize( - modulus_n:, - public_exponent_e:, - private_exponent_d: nil, - prime_factor_p: nil, - prime_factor_q: nil, - d_p: nil, - d_q: nil, - q_inv: nil - ) - if !modulus_n - raise ArgumentError, "Required modulus_n is missing" - elsif !public_exponent_e - raise ArgumentError, "Required public_exponent_e is missing" + def initialize(n:, e:, d: nil, p: nil, q: nil, dp: nil, dq: nil, qinv: nil, **keyword_arguments) # rubocop:disable Naming/UncommunicativeMethodParamName + super(**keyword_arguments) + + if !n + raise ArgumentError, "Required public field n is missing" + elsif !e + raise ArgumentError, "Required public field e is missing" else - @modulus_n = modulus_n - @public_exponent_e = public_exponent_e - @private_exponent_d = private_exponent_d - @prime_factor_p = prime_factor_p - @prime_factor_q = prime_factor_q - @d_p = d_p - @d_q = d_q - @q_inv = q_inv + private_fields = { d: d, p: p, q: q, dp: dp, dq: dq, qinv: qinv } + + if private_fields.values.all?(&:nil?) || private_fields.values.none?(&:nil?) + @n = n + @e = e + @d = d + @p = p + @q = q + @dp = dp + @dq = dq + @qinv = qinv + else + missing = private_fields.detect { |_k, v| v.nil? }[0] + raise ArgumentError, "Incomplete private fields, #{missing} is missing" + end end end - def serialize - CBOR.encode( + def map + map = super.merge( Base::LABEL_KTY => KTY_RSA, - LABEL_N => modulus_n, - LABEL_E => public_exponent_e, - LABEL_D => private_exponent_d, - LABEL_P => prime_factor_p, - LABEL_Q => prime_factor_q, - LABEL_D_P => d_p, - LABEL_D_Q => d_q, - LABEL_Q_INV => q_inv + LABEL_N => n, + LABEL_E => e, + LABEL_D => d, + LABEL_P => p, + LABEL_Q => q, + LABEL_DP => dp, + LABEL_DQ => dq, + LABEL_QINV => qinv ) + + map.reject { |_k, v| v.nil? } end def to_pkey pkey = OpenSSL::PKey::RSA.new - pkey.set_key(bn(modulus_n), bn(public_exponent_e), bn(private_exponent_d)) - pkey.set_factors(bn(prime_factor_p), bn(prime_factor_q)) - pkey.set_crt_params(bn(d_p), bn(d_q), bn(q_inv)) + if pkey.respond_to?(:set_key) + pkey.set_key(bn(n), bn(e), bn(d)) + else + pkey.n = bn(n) + pkey.e = bn(e) + pkey.d = bn(d) + end + if pkey.respond_to?(:set_factors) + pkey.set_factors(bn(p), bn(q)) + else + pkey.p = bn(p) + pkey.q = bn(q) + end + + if pkey.respond_to?(:set_crt_params) + pkey.set_crt_params(bn(dp), bn(dq), bn(qinv)) + else + pkey.dmp1 = bn(dp) + pkey.dmq1 = bn(dq) + pkey.iqmp = bn(qinv) + end + pkey end - def self.from_map(map) - enforce_type(map, KTY_RSA, "Not an RSA key") - - new(modulus_n: map[LABEL_N], public_exponent_e: map[LABEL_E]) + def self.keyword_arguments_for_initialize(map) + { + n: map[LABEL_N], + e: map[LABEL_E], + d: map[LABEL_D], + p: map[LABEL_P], + q: map[LABEL_Q], + dp: map[LABEL_DP], + dq: map[LABEL_DQ], + qinv: map[LABEL_QINV] + } end private def bn(data)