module Aws::Sigv4::AsymmetricCredentials

def self.derive_asymmetric_key(access_key_id, secret_access_key)

Returns:
  • (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