|
9 | 9 |
|
10 | 10 | namespace spns::hive {
|
11 | 11 |
|
12 |
| -void verify_signature(std::string_view sig_msg, const Signature& sig, const Ed25519PK& pubkey) { |
| 12 | +void verify_signature(std::string_view sig_msg, const Signature& sig, const Ed25519PK& pubkey, std::string_view descr) { |
13 | 13 | if (0 != crypto_sign_verify_detached(sig, as_usv(sig_msg).data(), sig_msg.size(), pubkey))
|
14 |
| - throw signature_verify_failure{"Signature verification failed"}; |
| 14 | + throw signature_verify_failure{std::string{descr} + " verification failed"}; |
| 15 | +} |
| 16 | + |
| 17 | +namespace { |
| 18 | + constexpr std::byte SUBACC_FLAG_READ{0b0001}; |
| 19 | + constexpr std::byte SUBACC_FLAG_ANY_PREFIX{0b1000}; |
15 | 20 | }
|
16 | 21 |
|
17 | 22 | /// Throws signature_verify_failure on signature failure.
|
18 | 23 | void verify_storage_signature(
|
19 | 24 | std::string_view sig_msg,
|
20 | 25 | const Signature& sig,
|
21 |
| - const Ed25519PK& pubkey, |
22 |
| - const std::optional<SubkeyTag>& subkey_tag) { |
| 26 | + const SwarmPubkey& pubkey, |
| 27 | + const std::optional<Subaccount>& subaccount) { |
| 28 | + |
| 29 | + if (subaccount) { |
| 30 | + // Parse the subaccount tag: |
| 31 | + // prefix aka netid (05 for session ids, 03 for groups): |
| 32 | + auto prefix = subaccount->tag[0]; |
| 33 | + // read/write/etc. flags: |
| 34 | + auto flags = subaccount->tag[1]; |
| 35 | + |
| 36 | + // If you don't have the read bit we can't help you: |
| 37 | + if ((flags & SUBACC_FLAG_READ) == std::byte{0}) |
| 38 | + throw signature_verify_failure{"Invalid subaccount: this subaccount does not have read permission"}; |
23 | 39 |
|
24 |
| - if (subkey_tag) { |
25 |
| - // H(c || A, key="OxenSSSubkey") |
26 |
| - auto verify_pubkey = blake2b_keyed<Ed25519PK>(subkey_tag_hash_key, *subkey_tag, pubkey); |
| 40 | + // Unless the subaccount has the "any prefix" flag, check that the prefix matches the |
| 41 | + // account prefix: |
| 42 | + if ((flags & SUBACC_FLAG_ANY_PREFIX) == std::byte{0} && |
| 43 | + prefix != pubkey.id[0]) |
| 44 | + throw signature_verify_failure{"Invalid subaccount: subaccount and main account have mismatched network prefix"}; |
27 | 45 |
|
28 |
| - // c + H(...) |
29 |
| - crypto_core_ed25519_scalar_add(verify_pubkey, *subkey_tag, verify_pubkey); |
| 46 | + // Verify that the main account has signed the subaccount tag: |
| 47 | + verify_signature(subaccount->tag.sv(), subaccount->sig, pubkey.ed25519, "Subaccount auth signature"); |
30 | 48 |
|
31 |
| - // (c + H(...)) A |
32 |
| - if (0 != crypto_scalarmult_ed25519_noclamp(verify_pubkey, verify_pubkey, pubkey)) |
33 |
| - throw signature_verify_failure{"Failed to compute subkey: scalarmult failed"}; |
| 49 | + // the subaccount pubkey (starts at [4]; [2] and [3] are future use/null padding): |
| 50 | + Ed25519PK sub_pk; |
| 51 | + std::memcpy(sub_pk.data(), &subaccount->tag[4], 32); |
34 | 52 |
|
35 |
| - verify_signature(sig_msg, sig, verify_pubkey); |
| 53 | + // Verify that the subaccount pubkey signed this message (and thus is allowed, transitively, |
| 54 | + // since the main account signed the subaccount): |
| 55 | + verify_signature(sig_msg, sig, sub_pk, "Subaccount main signature"); |
36 | 56 |
|
37 | 57 | } else {
|
38 |
| - verify_signature(sig_msg, sig, pubkey); |
| 58 | + verify_signature(sig_msg, sig, pubkey.ed25519); |
39 | 59 | }
|
40 | 60 | }
|
41 | 61 |
|
|
0 commit comments