Class: HPKE
Defined Under Namespace
Modules: Util Classes: Context, ContextR, ContextS, DHKEM, HKDF
Constant Summary collapse
- DHKEM_P256_HKDF_SHA256 =
Algorithm Identifiers DHKEM RFC 9180, Section 7.1 Table 2
0x0010- DHKEM_P384_HKDF_SHA384 =
0x0011- DHKEM_P521_HKDF_SHA512 =
0x0012- DHKEM_X25519_HKDF_SHA256 =
0x0020- DHKEM_X448_HKDF_SHA512 =
0x0021- AVAILABLE_KEM =
[ DHKEM_P256_HKDF_SHA256, DHKEM_P384_HKDF_SHA384, DHKEM_P521_HKDF_SHA512, DHKEM_X25519_HKDF_SHA256, DHKEM_X448_HKDF_SHA512 ]
- HKDF_SHA256 =
HKDF RFC 9180, Section 7.2, Table 3
0x0001- HKDF_SHA384 =
0x0002- HKDF_SHA512 =
0x0003- AVAILABLE_KDF =
[ HKDF_SHA256, HKDF_SHA384, HKDF_SHA512 ]
- AES_128_GCM =
AEAD RFC 9180, Section 7.3, Table 5
0x0001- AES_256_GCM =
0x0002- CHACHA20_POLY1305 =
0x0003- EXPORT_ONLY =
0xffff- AVAILABLE_AEAD =
[ AES_128_GCM, AES_256_GCM, CHACHA20_POLY1305, EXPORT_ONLY ]
- CIPHERS =
{ AES_128_GCM => { name: 'aes-128-gcm', n_k: 16, n_n: 12, n_t: 16 }, AES_256_GCM => { name: 'aes-256-gcm', n_k: 32, n_n: 12, n_t: 16 }, CHACHA20_POLY1305 => { name: 'chacha20-poly1305', n_k: 32, n_n: 12, n_t: 16 }, EXPORT_ONLY => { } }
- MODES =
{ base: 0x00, psk: 0x01, auth: 0x02, auth_psk: 0x03 }
- VERSION =
"1.0.2"
Instance Attribute Summary collapse
-
#aead_id ⇒ Object
readonly
Returns the value of attribute aead_id.
-
#aead_name ⇒ Object
readonly
Returns the value of attribute aead_name.
-
#hkdf ⇒ Object
readonly
Returns the value of attribute hkdf.
-
#kem ⇒ Object
readonly
Returns the value of attribute kem.
-
#n_k ⇒ Object
readonly
Returns the value of attribute n_k.
-
#n_n ⇒ Object
readonly
Returns the value of attribute n_n.
-
#n_t ⇒ Object
readonly
Returns the value of attribute n_t.
Instance Method Summary collapse
- #aead_decrypt(key, nonce, aad, ct) ⇒ Object
- #aead_encrypt(key, nonce, aad, pt) ⇒ Object
- #export(exporter_secret, exporter_context, len) ⇒ Object
-
#initialize(kem_id, kdf_id, aead_id) ⇒ HPKE
constructor
A new instance of HPKE.
- #setup_auth_psk_r(enc, sk_r, info, psk, psk_id, pk_s) ⇒ Object
- #setup_auth_psk_s(pk_r, info, psk, psk_id, sk_s) ⇒ Object
- #setup_auth_psk_s_fixed(pk_r, info, psk, psk_id, sk_s, ikm_e) ⇒ Object
- #setup_auth_r(enc, sk_r, info, pk_s) ⇒ Object
- #setup_auth_s(pk_r, info, sk_s) ⇒ Object
- #setup_auth_s_fixed(pk_r, info, sk_s, ikm_e) ⇒ Object
- #setup_base_r(enc, sk_r, info) ⇒ Object
-
#setup_base_s(pk_r, info) ⇒ Object
public facing APIs.
-
#setup_base_s_fixed(pk_r, info, ikm_e) ⇒ Object
for testing purposes.
- #setup_psk_r(enc, sk_r, info, psk, psk_id) ⇒ Object
- #setup_psk_s(pk_r, info, psk, psk_id) ⇒ Object
- #setup_psk_s_fixed(pk_r, info, psk, psk_id, ikm_e) ⇒ Object
Methods included from Util
Constructor Details
#initialize(kem_id, kdf_id, aead_id) ⇒ HPKE
Returns a new instance of HPKE.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/hpke.rb', line 74 def initialize(kem_id, kdf_id, aead_id) raise Exception.new('Unsupported AEAD') unless AVAILABLE_AEAD.include?(aead_id) @kem = case kem_id when DHKEM_P256_HKDF_SHA256 then DHKEM::EC::P_256.new(HKDF_SHA256) when DHKEM_P384_HKDF_SHA384 then DHKEM::EC::P_384.new(HKDF_SHA384) when DHKEM_P521_HKDF_SHA512 then DHKEM::EC::P_521.new(HKDF_SHA512) when DHKEM_X25519_HKDF_SHA256 then DHKEM::X25519.new(HKDF_SHA256) when DHKEM_X448_HKDF_SHA512 then DHKEM::X448.new(HKDF_SHA512) else raise Exception.new('Unsupported KEM') end @hkdf = case kdf_id when HKDF_SHA256 then HKDF.new(HKDF_SHA256) when HKDF_SHA384 then HKDF.new(HKDF_SHA384) when HKDF_SHA512 then HKDF.new(HKDF_SHA512) else raise Exception.new('Unsupported KDF') end @aead_id = aead_id @aead_name = CIPHERS[aead_id][:name] @n_k = CIPHERS[aead_id][:n_k] @n_n = CIPHERS[aead_id][:n_n] @n_t = CIPHERS[aead_id][:n_t] end |
Instance Attribute Details
#aead_id ⇒ Object (readonly)
Returns the value of attribute aead_id.
12 13 14 |
# File 'lib/hpke.rb', line 12 def aead_id @aead_id end |
#aead_name ⇒ Object (readonly)
Returns the value of attribute aead_name.
12 13 14 |
# File 'lib/hpke.rb', line 12 def aead_name @aead_name end |
#hkdf ⇒ Object (readonly)
Returns the value of attribute hkdf.
12 13 14 |
# File 'lib/hpke.rb', line 12 def hkdf @hkdf end |
#kem ⇒ Object (readonly)
Returns the value of attribute kem.
12 13 14 |
# File 'lib/hpke.rb', line 12 def kem @kem end |
#n_k ⇒ Object (readonly)
Returns the value of attribute n_k.
12 13 14 |
# File 'lib/hpke.rb', line 12 def n_k @n_k end |
#n_n ⇒ Object (readonly)
Returns the value of attribute n_n.
12 13 14 |
# File 'lib/hpke.rb', line 12 def n_n @n_n end |
#n_t ⇒ Object (readonly)
Returns the value of attribute n_t.
12 13 14 |
# File 'lib/hpke.rb', line 12 def n_t @n_t end |
Instance Method Details
#aead_decrypt(key, nonce, aad, ct) ⇒ Object
207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/hpke.rb', line 207 def aead_decrypt(key, nonce, aad, ct) ct_body = ct[0, ct.length - n_t] tag = ct[-n_t, n_t] cipher = OpenSSL::Cipher.new(aead_name) cipher.decrypt cipher.key = key cipher.iv = nonce cipher.auth_tag = tag cipher.auth_data = aad cipher.padding = 0 cipher.update(ct_body) << cipher.final end |
#aead_encrypt(key, nonce, aad, pt) ⇒ Object
196 197 198 199 200 201 202 203 204 205 |
# File 'lib/hpke.rb', line 196 def aead_encrypt(key, nonce, aad, pt) cipher = OpenSSL::Cipher.new(aead_name) cipher.encrypt cipher.key = key cipher.iv = nonce cipher.auth_data = aad cipher.padding = 0 s = cipher.update(pt) << cipher.final s + cipher.auth_tag end |
#export(exporter_secret, exporter_context, len) ⇒ Object
192 193 194 |
# File 'lib/hpke.rb', line 192 def export(exporter_secret, exporter_context, len) @hkdf.(exporter_secret, 'sec', exporter_context, len, suite_id) end |
#setup_auth_psk_r(enc, sk_r, info, psk, psk_id, pk_s) ⇒ Object
150 151 152 153 |
# File 'lib/hpke.rb', line 150 def setup_auth_psk_r(enc, sk_r, info, psk, psk_id, pk_s) shared_secret = @kem.auth_decap(enc, sk_r, pk_s) key_schedule_r(MODES[:auth_psk], shared_secret, info, psk, psk_id) end |
#setup_auth_psk_s(pk_r, info, psk, psk_id, sk_s) ⇒ Object
141 142 143 144 145 146 147 148 |
# File 'lib/hpke.rb', line 141 def setup_auth_psk_s(pk_r, info, psk, psk_id, sk_s) encap_result = @kem.auth_encap(pk_r, sk_s) { enc: encap_result[:enc], context_s: key_schedule_s(MODES[:auth_psk], encap_result[:shared_secret], info, psk, psk_id), shared_secret: encap_result[:shared_secret] } end |
#setup_auth_psk_s_fixed(pk_r, info, psk, psk_id, sk_s, ikm_e) ⇒ Object
183 184 185 186 187 188 189 190 |
# File 'lib/hpke.rb', line 183 def setup_auth_psk_s_fixed(pk_r, info, psk, psk_id, sk_s, ikm_e) encap_result = @kem.auth_encap_fixed(pk_r, sk_s, ikm_e) { enc: encap_result[:enc], context_s: key_schedule_s(MODES[:auth_psk], encap_result[:shared_secret], info, psk, psk_id), shared_secret: encap_result[:shared_secret] } end |
#setup_auth_r(enc, sk_r, info, pk_s) ⇒ Object
136 137 138 139 |
# File 'lib/hpke.rb', line 136 def setup_auth_r(enc, sk_r, info, pk_s) shared_secret = @kem.auth_decap(enc, sk_r, pk_s) key_schedule_r(MODES[:auth], shared_secret, info, DEFAULT_PSK, DEFAULT_PSK_ID) end |
#setup_auth_s(pk_r, info, sk_s) ⇒ Object
127 128 129 130 131 132 133 134 |
# File 'lib/hpke.rb', line 127 def setup_auth_s(pk_r, info, sk_s) encap_result = @kem.auth_encap(pk_r, sk_s) { enc: encap_result[:enc], context_s: key_schedule_s(MODES[:auth], encap_result[:shared_secret], info, DEFAULT_PSK, DEFAULT_PSK_ID), shared_secret: encap_result[:shared_secret] } end |
#setup_auth_s_fixed(pk_r, info, sk_s, ikm_e) ⇒ Object
174 175 176 177 178 179 180 181 |
# File 'lib/hpke.rb', line 174 def setup_auth_s_fixed(pk_r, info, sk_s, ikm_e) encap_result = @kem.auth_encap_fixed(pk_r, sk_s, ikm_e) { enc: encap_result[:enc], context_s: key_schedule_s(MODES[:auth], encap_result[:shared_secret], info, DEFAULT_PSK, DEFAULT_PSK_ID), shared_secret: encap_result[:shared_secret] } end |
#setup_base_r(enc, sk_r, info) ⇒ Object
108 109 110 111 |
# File 'lib/hpke.rb', line 108 def setup_base_r(enc, sk_r, info) shared_secret = @kem.decap(enc, sk_r) key_schedule_r(MODES[:base], shared_secret, info, DEFAULT_PSK, DEFAULT_PSK_ID) end |
#setup_base_s(pk_r, info) ⇒ Object
public facing APIs
99 100 101 102 103 104 105 106 |
# File 'lib/hpke.rb', line 99 def setup_base_s(pk_r, info) encap_result = @kem.encap(pk_r) { enc: encap_result[:enc], context_s: key_schedule_s(MODES[:base], encap_result[:shared_secret], info, DEFAULT_PSK, DEFAULT_PSK_ID), shared_secret: encap_result[:shared_secret] } end |
#setup_base_s_fixed(pk_r, info, ikm_e) ⇒ Object
for testing purposes
156 157 158 159 160 161 162 163 |
# File 'lib/hpke.rb', line 156 def setup_base_s_fixed(pk_r, info, ikm_e) encap_result = @kem.encap_fixed(pk_r, ikm_e) { enc: encap_result[:enc], context_s: key_schedule_s(MODES[:base], encap_result[:shared_secret], info, DEFAULT_PSK, DEFAULT_PSK_ID), shared_secret: encap_result[:shared_secret] } end |
#setup_psk_r(enc, sk_r, info, psk, psk_id) ⇒ Object
122 123 124 125 |
# File 'lib/hpke.rb', line 122 def setup_psk_r(enc, sk_r, info, psk, psk_id) shared_secret = @kem.decap(enc, sk_r) key_schedule_r(MODES[:psk], shared_secret, info, psk, psk_id) end |
#setup_psk_s(pk_r, info, psk, psk_id) ⇒ Object
113 114 115 116 117 118 119 120 |
# File 'lib/hpke.rb', line 113 def setup_psk_s(pk_r, info, psk, psk_id) encap_result = @kem.encap(pk_r) { enc: encap_result[:enc], context_s: key_schedule_s(MODES[:psk], encap_result[:shared_secret], info, psk, psk_id), shared_secret: encap_result[:shared_secret] } end |
#setup_psk_s_fixed(pk_r, info, psk, psk_id, ikm_e) ⇒ Object
165 166 167 168 169 170 171 172 |
# File 'lib/hpke.rb', line 165 def setup_psk_s_fixed(pk_r, info, psk, psk_id, ikm_e) encap_result = @kem.encap_fixed(pk_r, ikm_e) { enc: encap_result[:enc], context_s: key_schedule_s(MODES[:psk], encap_result[:shared_secret], info, psk, psk_id), shared_secret: encap_result[:shared_secret] } end |