module Aws::Sigv4::AsymmetricCredentials
def self.derive_asymmetric_key(access_key_id, secret_access_key)
-
(OpenSSL::PKey::EC, Hash)
-
def self.derive_asymmetric_key(access_key_id, secret_access_key) check_openssl_support! label = 'AWS4-ECDSA-P256-SHA256' bit_len = 256 counter = 0x1 input_key = "AWS4A#{secret_access_key}" d = 0 # d will end up being the private key while true do kdf_context = access_key_id.unpack('C*') + [counter].pack('C').unpack('C') #1 byte for counter input = label.unpack('C*') + [0x00] + kdf_context + [bit_len].pack('L>').unpack('CCCC') # 4 bytes (change endianess) k0 = OpenSSL::HMAC.digest("SHA256", input_key, ([0, 0, 0, 0x01] + input).pack('C*')) c = be_bytes_to_num( k0.unpack('C*') ) if c <= N_MINUS_2 d = c + 1 break elsif counter > 0xFF raise 'Counter exceeded 1 byte - unable to get asym creds' else counter += 1 end end # compute the public key group = OpenSSL::PKey::EC::Group.new('prime256v1') public_key = group.generator.mul(d) ec = generate_ec(public_key, d) # pk_x and pk_y are not needed for signature, but useful in verification/testing pk_b = public_key.to_octet_string(:uncompressed).unpack('C*') # 0x04 byte followed by 2 32-byte integers pk_x = be_bytes_to_num(pk_b[1,32]) pk_y = be_bytes_to_num(pk_b[33,32]) [ec, {ec: ec, public_key: public_key, pk_x: pk_x, pk_y: pk_y, d: d}] end