Module: Robocap::SDK::RSAOAEP

Defined in:
lib/robocap/sdk/rsa_oaep.rb

Class Method Summary collapse

Class Method Details

.cipher_len_for_key(key) ⇒ Object



13
14
15
# File 'lib/robocap/sdk/rsa_oaep.rb', line 13

def cipher_len_for_key(key)
  key.n.num_bytes
end

.unwrap_aes_key(ciphertext, private_key) ⇒ Object



66
67
68
69
70
71
72
# File 'lib/robocap/sdk/rsa_oaep.rb', line 66

def unwrap_aes_key(ciphertext, private_key)
  unwrap_key(
    ciphertext, private_key,
    plain_len: Config::AES_KEY_BYTES,
    cipher_len: Config::RSA_CIPHERTEXT_BYTES,
  )
end

.unwrap_cek(ciphertext, private_key) ⇒ Object



82
83
84
85
86
87
88
89
90
# File 'lib/robocap/sdk/rsa_oaep.rb', line 82

def unwrap_cek(ciphertext, private_key)
  unwrap_key(
    ciphertext, private_key,
    plain_len: Config::CEK_BYTES,
    cipher_len: Config::RSA_2048_CIPHERTEXT_BYTES,
    decode_error: ErrorCode::ERR_CENC_CEKA_WRAP,
    length_error: ErrorCode::ERR_CENC_CEKA_LENGTH,
  )
end

.unwrap_key(ciphertext, private_key, plain_len:, cipher_len: nil, decode_error: ErrorCode::ERR_K2_DECODE, length_error: ErrorCode::ERR_K2_PLAINTEXT_LENGTH) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/robocap/sdk/rsa_oaep.rb', line 34

def unwrap_key(ciphertext, private_key,
               plain_len:, cipher_len: nil,
               decode_error: ErrorCode::ERR_K2_DECODE,
               length_error: ErrorCode::ERR_K2_PLAINTEXT_LENGTH)
  expected = cipher_len || cipher_len_for_key(private_key)
  unless ciphertext.bytesize == expected
    raise Error.new(code: decode_error, message: "RSA ciphertext must be #{expected} bytes")
  end
  plaintext = begin
    private_key.decrypt(
      ciphertext,
      rsa_padding_mode: 'oaep',
      rsa_oaep_md: 'sha256',
      rsa_mgf1_md: 'sha256',
    )
  rescue OpenSSL::PKey::PKeyError, OpenSSL::PKey::RSAError => exc
    raise Error.new(code: decode_error, message: 'RSA-OAEP unwrap failed', detail: { reason: exc.message })
  end
  unless plaintext.bytesize == plain_len
    raise Error.new(code: length_error, message: "Decrypted key length #{plaintext.bytesize} != #{plain_len}")
  end
  plaintext
end

.wrap_aes_key(device_aes, public_key) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/robocap/sdk/rsa_oaep.rb', line 58

def wrap_aes_key(device_aes, public_key)
  wrap_key(
    device_aes, public_key,
    plain_len: Config::AES_KEY_BYTES,
    cipher_len: Config::RSA_CIPHERTEXT_BYTES,
  )
end

.wrap_cek(cek, public_key) ⇒ Object



74
75
76
77
78
79
80
# File 'lib/robocap/sdk/rsa_oaep.rb', line 74

def wrap_cek(cek, public_key)
  wrap_key(
    cek, public_key,
    plain_len: Config::CEK_BYTES,
    cipher_len: Config::RSA_2048_CIPHERTEXT_BYTES,
  )
end

.wrap_key(plaintext, public_key, plain_len:, cipher_len: nil) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/robocap/sdk/rsa_oaep.rb', line 17

def wrap_key(plaintext, public_key, plain_len:, cipher_len: nil)
  unless plaintext.bytesize == plain_len
    raise ArgumentError, "plaintext must be #{plain_len} bytes (got #{plaintext.bytesize})"
  end
  expected = cipher_len || cipher_len_for_key(public_key)
  ciphertext = public_key.encrypt(
    plaintext,
    rsa_padding_mode: 'oaep',
    rsa_oaep_md: 'sha256',
    rsa_mgf1_md: 'sha256',
  )
  unless ciphertext.bytesize == expected
    raise ArgumentError, "RSA ciphertext length #{ciphertext.bytesize} != #{expected}"
  end
  ciphertext
end