rest.rst (19501B)
1 .. 2 This file is part of Frosix 3 Copyright (C) 2022, 2023 Joel Urech 4 5 Frosix is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Frosix is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 Frosix; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 16 @author Christian Grothoff 17 @author Joel Urech 18 19 ======== 20 REST API 21 ======== 22 23 .. _config: 24 25 ----------------------- 26 Receiving Configuration 27 ----------------------- 28 29 .. http:get:: /config 30 31 Obtain the configuration details of the provider. 32 33 **Response:** 34 35 Returns a `ProviderConfigurationResponse`_. 36 37 38 .. _ProviderConfigurationResponse: 39 .. ts:def:: ProviderConfigurationResponse 40 41 interface ProviderConfigurationResponse { 42 43 // Protocol identifier, clarifies that this is a Frosix provider. 44 name: "frosix"; 45 46 // libtool-style representation of the Exchange protocol version, see 47 // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning 48 // The format is "current:revision:age". 49 version: string; 50 51 // What is the name of this provider? 52 business_name: string; 53 54 // Supported authorization methods. 55 methods: AuthorizationMethodConfig[]; 56 57 // Payment required to create a key. 58 // Not yet implemented! 59 // key_creation_fee: Amount; 60 61 // Salt value with 128 bits of entropy. 62 // Different providers will use different high-entropy salt values. 63 // The resulting **provider salt** is then used in various operations to ensure 64 // cryptographic operations differ by provider. 65 // A provider must never change its salt value. 66 provider_salt: string; 67 68 // Public key of this provider. 69 public_key: string; 70 71 } 72 73 .. _AuthorizationMethodConfig: 74 .. ts:def:: AuthorizationMethodConfig 75 76 interface AuthorizationMethodConfig { 77 // Name of the authorization method. 78 type: string; 79 80 // Fee for issuing a signature share using this method. 81 // Not yet implemented! 82 // cost: Amount; 83 84 } 85 86 87 .. _terms: 88 89 -------------------------- 90 Receiving Terms of Service 91 -------------------------- 92 93 .. http:get:: /terms 94 95 Obtain the terms of service of the provider. 96 // Not yet implemented! 97 98 99 .. _seed: 100 101 ---- 102 Seed 103 ---- 104 105 .. http:get:: /seed 106 107 Returns an high-entropy seed. Binary data in the HTTP body. 108 This API should be used every time the clients need high entropy. 109 The entropy returned MUST be mixed with locally generated entropy. 110 111 112 .. _key: 113 114 -------------- 115 Key Generation 116 -------------- 117 118 119 Distributed Key Generation 120 ^^^^^^^^^^^^^^^^^^^^^^^^^^ 121 122 .. http:post:: /dkg-commitment/$ID/ 123 124 Let the provider compute a commitment for a polynomial with degree threshold-1. 125 ``$ID`` is the SHA-512 hash over the following data in Crockford base32 endoding: `ContextString`, `AuthHash`, `Identifier`, `NumOfParticipants`, `Threshold`, `PublicProviderSalt`, "FROSIX-DKG-ID". 126 127 **Request:** 128 129 Upload a `DkgCommitmentRequest`. 130 131 **Response:** 132 133 :http:statuscode:`201 Created`: 134 The provider responds with a `DkgCommitmentResponse`. 135 136 **Details:** 137 138 .. _DkgCommitmentRequest: 139 .. ts:def:: DkgCommitmentRequest 140 141 interface DkgCommitmentRequest { 142 143 // Unique identifier within the group. 144 provider_index: Identifier; 145 146 // Minimum number of participants needed to sign a message. 147 threshold: Threshold; 148 149 // ContextString is the main source of entropy to sample the commitments and should draw its entropy from several sources (e.g. with GET /seed from each participating provider). 150 context_string: ContextString; 151 152 // Salted hash of authentication data, i.e. phone number, e-mail address, ... 153 // Or hash of the public key used to verify the secret answer of a security question. 154 auth_hash: AuthHash; 155 156 // Public keys of all participating providers. 157 // Number of public key equals the total number of participants (n). 158 providers_public_keys: ProviderPublicKey[]; 159 160 } 161 162 .. _DkgCommitmentResponse: 163 .. ts:def:: DkgCommitmentResponse 164 165 interface DkgCommitmentResponse { 166 167 // Unique identifier within the group 168 provider_index: Identifier; 169 170 // List of commitments, corresponding to the computed polynomial. 171 dkg_commitment: DkgCommitment[threshold]; 172 173 // Zero Knowledge Proof of the corresponding secret of the computed polynomial. 174 zkp: DkgZkp; 175 176 // Public Key to derive an symmetric key to encrypt the secret share intended for this provider (ECDHE). 177 provider_public_key: EphemeralPublicKey; 178 } 179 180 .. _DkgZkp: 181 .. ts:def:: DkgZkp 182 183 interface DkgZkp { 184 r: R; 185 z: z; 186 } 187 188 189 .. http:post:: /dkg-shares/$ID 190 191 Upload the DKG commitments of all other participants and receive encrypted shares for all other participants. 192 ``$ID`` is the SHA-512 hash over the following data in Crockford base32 endoding: `ContextString`, `AuthHash`, `Identifier`, `NumOfParticipants`, `Threshold`, `PublicProviderSalt`, "FROSIX-DKG-ID". 193 194 **Request:** 195 196 Upload a `DkgSecretSharesRequest`_. 197 198 **Response:** 199 200 :http:statuscode:`201 Created`: 201 The provider responds with a `DkgSecretSharesResponse`_. 202 203 **Details:** 204 205 .. _DkgSecretSharesRequest: 206 .. ts:def:: DkgSecretSharesRequest: 207 208 interface DkgSecretSharesRequest { 209 210 // Identifier within the group. 211 provider_index: Identifier; 212 213 // Minimum number of participants needed to sign a message. 214 threshold: Threshold; 215 216 // Number of participants participating in the distributed key generation. 217 num_of_participants: NumOfParticipants; 218 219 // ContextString is the source of entropy to recover commitments. 220 context_string: ContextString; 221 222 // Salted hash of some challenge data, i.e. phone number, e-mail address, ... 223 // Or hash of the public key used to verify the secret answer of a security question. 224 auth_hash: AuthHash; 225 226 // Public keys of all participating providers. 227 // Number of public key equals total number of participants (n). 228 providers_public_keys: ProviderPublicKey[]; 229 230 // The commitments of all participants 231 dkg_commitments: DkgCommitmentResponse[num_of_participants - 1]; 232 233 } 234 235 .. _DkgSecretSharesResponse: 236 .. ts:def:: DkgSecretSharesResponse: 237 238 interface DkgSecretSharesResponse { 239 240 // The secret shares 241 secret_shares: DkgSecretShare[num_of_participants - 1]; 242 243 } 244 245 .. _DkgSecretShare: 246 .. ts:def:: DkgSecretShare: 247 248 interface DkgSecretShare { 249 250 // Identifier of the target participant 251 target: Identifier; 252 253 // identifier of the issuer 254 issuer: Identifier; 255 256 // Ephemeral key 257 ephemeral_key: EphemeralKey; 258 259 enc_secret_share_data: [[ 260 261 // The secret share - symmetric encrypted 262 secret_share: SecretShare; ]] 263 264 } 265 266 267 .. http:post:: /dkg-key/$ID 268 269 Upload all encrypted secret shares intended for this participant. 270 ``$ID`` is the SHA-512 hash over the following data in Crockford base32 endoding: `ContextString`, `AuthHash`, `Identifier`, `NumOfParticipants`, `Threshold`, `PublicProviderSalt`, "FROSIX-DKG-ID". 271 272 **Request:** 273 274 Upload a `KeyGenerateRequest`_. 275 276 **Response:** 277 278 :http:statuscode:`204 No Content`: 279 Key pair was successfully created and stored. 280 :http:statuscode:`404 Not Found`: 281 The provider does not know the provided ``$ID``. 282 :http:statuscode:`409 Conflict`: 283 The service already has a key pair stored under the resulting ``$ID`` (hash of resulting public key). 284 :http:statuscode:`402 Payment required`: 285 If the desired storage duration is longer than the default value in the terms of service of the provider, the provider must be paid additionally. 286 287 **Details:** 288 289 .. _KeyGenerateRequest: 290 .. ts:def:: KeyGenerateRequest: 291 292 interface KeyGenerateRequest { 293 294 // Identifier within the group. 295 provider_index: Identifier; 296 297 // Minimum number of participants needed to sign a message. (needed to calculate secret polynomail) 298 threshold: Threshold; 299 300 // ContextString is the source of entropy to recover the secret value behind the providers commitment. 301 context_string: ContextString; 302 303 // Salted hash of some challenge data, i.e. phone number, e-mail address, ... 304 // Or hash of the public key used to verify the secret answer of a security question. 305 auth_hash: AuthHash; 306 307 // Public keys of all participating providers. 308 // Number of public key equals total number of participants (n). 309 providers_public_keys: ProviderPublicKey[]; 310 311 // For how many years from now would the client like us to store the truth? 312 expiration: Years; 313 314 // All secret shares targeting this participant 315 secret_shares: DkgSecretShare[num_of_participants - 1]; 316 317 } 318 319 .. _KeyGenerateResponse: 320 .. ts:def:: KeyGenerateResponse: 321 322 interface KeyGenerateResponse { 323 324 // Public Key of created Distributed Secret Key 325 public_key: PublicKey 326 327 // The signature is over the public key and the received authentication hash. 328 // This signature allows to verify the correctness of the authentication hash and to proof to a third person that this provider is involved in this signing group. 329 provider_signature: ProviderSignature 330 331 } 332 333 334 .. _challenge: 335 336 ----------------- 337 Challenge Request 338 ----------------- 339 340 .. http:post:: /auth-request/$ID 341 342 Let the provider create and send a challenge-code. 343 ``$ID`` is the SHA-512 hash over the following data in Crockford base32 endoding: `EncryptionKey`, `MessageHash`, "FROSIX-AUTH". 344 345 **Request:** 346 347 The request must be a `ChallengeCodeRequest`_. 348 349 **Response:** 350 351 :http:statuscode:`200 OK`: 352 The provider responds with an empty body. 353 :http:statuscode:`402 Payment Required`: 354 The provider requires payment to issue a challenge code. 355 356 **Details:** 357 358 .. _ChallengeCodeRequest: 359 .. ts:def:: ChallengeCodeRequest: 360 361 interface ChallengeCodeRequest { 362 363 // Encryption key 364 encryption_key: EncryptionKey; 365 366 // Authentication method 367 auth_method: AuthMethod; 368 369 // Authentication data 370 auth_data: AuthData; 371 372 // Authentication nonce 373 auth_nonce: AuthNonce; 374 375 // Hash of the message. 376 // The message is bound to the challenge code. A challenge code can therefore only be used for a specific message. 377 message_hash: MessageHash; 378 } 379 380 381 .. _sign: 382 383 ------- 384 Signing 385 ------- 386 387 .. http:post:: /sig-commitment/$ID 388 389 A provider first authenticates an incoming request and then issues a commitment, which is bound to the submitted message. 390 ``$ID`` is the SHA-512 hash over the following data in Crockford base32 endoding: `EncryptionKeyHash`, `MessageHash`, "FROSIX-SIG". 391 392 **Request:** 393 394 The request must be a `SignatureCommitmentRequest`_. 395 396 **Response:** 397 398 :http:statuscode:`200 OK`: 399 The provider responds with a `SignatureCommitmentResponse`_. 400 :http:statuscode:`403 Forbidden`: 401 The client failed the authentication challenge. 402 :http:statuscode:`404 Not Found`: 403 The provider does not know the provided ``$ID``. 404 :http:statuscode:`404 Not found`: 405 The provider does not know the given ``$ID``. 406 :http:statuscode:`410 Gone`: 407 The challenge has expired. 408 :http:statuscode:`429 Too Many Requests`: 409 Too many attempts. 410 411 **Details:** 412 413 .. _SignatureCommitmentRequest: 414 .. ts:def:: SignatureCommitmentRequest: 415 416 interface SigantureCommitmentRequest { 417 418 // Hash of the encryption key, used to identify the corresponding entry in the database. 419 encryption_key_hash: EncryptionKeyHash; 420 421 // Authentication method in order to authorize the incoming request. 422 auth_method: AuthMethod; 423 424 // (Optional) If its a challenge code based authentication, authentication data contains the hash of the challenge code. 425 auth_data: AuthData; 426 427 // (Optional) If its a security question, this authentication signature over the `MessageHash` is created with a private key which is derived from the secret answer. 428 auth_sig: AuthSig; 429 430 // (Optional) Public key to verify the `AuthSig` signature. Gets hashed and compared to the hash stored in the provider's database. 431 auth_pub: AuthPub; 432 433 // Hash of the message, serves as input for the key derivation function to sample a commitment. 434 message_hash: MessageHash; 435 436 } 437 438 .. _SignatureCommitmentResponse: 439 .. ts:def:: SignatureCommitmentResponse: 440 441 interface SignatureCommitmentResponse { 442 443 // First part of the commitment. 444 // Commitments are used to ensure, that every provider behaves well. 445 hiding_commitment: SigCommitment; 446 447 // Second part of the commitment. 448 binding_commitment: SigCommitment; 449 450 } 451 452 453 .. http:post:: /sig-share/$ID 454 455 Ask the provider to compute a signature share. 456 ``$ID`` is the SHA-512 hash over the following data in Crockford base32 endoding: `EncryptionKeyHash`, `MessageHash`, "FROSIX-SIG". 457 458 **Request:** 459 460 Upload a `SignatureShareRequest`. 461 462 **Response:** 463 464 :http:statuscode:`200 OK`: 465 The provider responds with a `SignatureShareResponse`. 466 :http:statuscode:`404 Not found`: 467 The provider does not know the given ``$ID``. 468 469 **Details:** 470 471 .. _SignatureShareRequest: 472 .. ts:def:: SignatureShareRequest 473 474 interface SignatureShareRequest { 475 476 // Symmetric key to decrypt the key material 477 encryption_key: EncryptionKey; 478 479 // Hash of the message 480 message_hash: MessageHash; 481 482 // Sorted list of commitments of all participating providers. 483 // The own commitment has to be included. 484 commitments: SignatureCommitmentResponse[]; 485 486 } 487 488 .. _SignatureCommmitment: 489 .. ts:def:: SignatureCommitment 490 491 interface SignatureCommitment { 492 493 // Identifier 494 identifier: Identifier; 495 496 // First part of the commitment. 497 // Commitments are used to ensure, that every provider behaves well. 498 hiding_commitment: SigCommitment; 499 500 // Second part of the commitment. 501 binding_commitment: SigCommitment; 502 503 } 504 505 .. _SignatureShareResponse: 506 .. ts:def:: SignatureShareResponse 507 508 interface SignatureShareResponse { 509 510 // The resulting signature share 511 signature_share: SigShare; 512 513 // The partial public key for convenience only - could be ommited 514 public_key_share: PublicKeyShare; 515 516 } 517 518 519 .. _delete-key: 520 521 ---------- 522 Delete Key 523 ---------- 524 525 .. http:delete:: /dkg-key/$ID 526 527 Deletes the key data if an entry is found with the ``$ID``. 528 ``$ID`` is the `EncryptionKeyHash`. 529 530 **Response:** 531 532 :http:statuscode:`200 OK`: 533 The provider responds with a `SignatureCommitmentResponse`_. 534 535 536 .. _encodings-ref: 537 538 ---------------- 539 Common encodings 540 ---------------- 541 542 This section describes how certain types of values are represented throughout the API. 543 544 .. _base32: 545 546 Binary Data 547 ^^^^^^^^^^^ 548 549 .. ts:def:: foobase 550 551 type Base32 = string; 552 553 Binary data is generally encoded using Crockford's variant of Base32 554 (http://www.crockford.com/wrmg/base32.html), except that "U" is not excluded 555 but also decodes to "V" to make OCR easy. We will still simply use the JSON 556 type "base32" and the term "Crockford Base32" in the text to refer to the 557 resulting encoding. 558 559 560 Hash codes 561 ^^^^^^^^^^ 562 Hash codes are strings representing base32 encoding of the respective 563 hashed data. See `base32`_. 564 565 .. ts:def:: HashCode 566 567 // 64-byte hash code. 568 type HashCode = string; 569 570 .. ts:def:: SHA512HashCode 571 572 type SHA512HashCode = HashCode; 573 574 .. ts:def:: PublicProviderSalt 575 576 type PublicProviderSalt: HashCode; 577 578 .. ts:def:: ContextString 579 580 // To generate a "good" ContextString, 581 // the client has to get fresh entropy from at least 582 // all participating providers (GET seed) and from itself. 583 type ContextString = SHA512HashCode; 584 585 .. ts:def:: MessageHash 586 587 // Hash of the message, which shall be signed. 588 type MessageHash = SHA512HashCode; 589 590 .. ts:def:: EncryptionKey 591 592 // The encryption key is used to encrypt and decrypt the key data stored in the provider's database. 593 type EncryptionKey = SHA512HashCode; 594 595 .. ts:def:: EncryptionKeyHash 596 597 // Hash of the encryption key. Used to identify the corresponding entry in the provider's database. 598 type EncryptionKeyHash = SHA512HashCode; 599 600 .. ts:def:: AuthHash 601 602 // The authentication hash is a salted hash of the authentication data which gets stored in the provider's database. 603 type AuthHash = SHA512HashCode; 604 605 .. ts:def:: AuthNonce 606 607 // Nonce used as salt to hash `AuthData` to receive `AuthHash`. 608 tpye AuthNonce = SHA512HashCode; 609 610 611 Curve25519 612 ^^^^^^^^^^ 613 32-byte values representig base32 encoding of either a point on Curve25519 or a scalar for operations on points on Curve 25519. 614 615 .. ts:def:: Cs25519Point 616 617 type Cs25519Point = string; 618 619 .. ts:def:: Cs25519Scalar 620 621 type Cs25519Scalar = string; 622 623 .. ts:def:: SigCommitment 624 625 type SigCommitment = Cs25519Point; 626 627 .. ts:def:: DkgCommitment 628 629 type DkgCommitment = Cs25519Point; 630 631 .. ts:def:: SecretShare 632 633 type SecretShare = Cs25519Scalar; 634 635 .. ts:def:: EddsaPublicKey 636 637 // EdDSA and ECDHE public keys always point on Curve25519 638 // and represented using the standard 256 bits Ed25519 compact format, 639 // converted to Crockford `Base32`. 640 type EddsaPublicKey = string; 641 642 .. ts:def:: EddsaPrivateKey 643 644 // EdDSA and ECDHE public keys always point on Curve25519 645 // and represented using the standard 256 bits Ed25519 compact format, 646 // converted to Crockford `Base32`. 647 type EddsaPrivateKey = string; 648 649 650 Signatures 651 ^^^^^^^^^^ 652 653 .. ts:def:: EddsaSignature 654 655 // EdDSA signatures are transmitted as 64-bytes `base32` 656 // binary-encoded objects with just the R and S values (base32_ binary-only). 657 type EddsaSignature = string; 658 659 .. ts:def:: R 660 661 // The signature challenge. 662 type R = Cs25519Point; 663 664 .. ts:def:: z 665 666 // A single share of the resulting signature. 667 type z = Cs25519Scalar; 668 669 .. ts:def:: ProviderSignature 670 671 // Signature of a provider over the public key and the authentication data. 672 type ProviderSignature = EddsaSignature; 673 674 .. ts:def:: AuthSig 675 676 // Signature over the message with a private key derived from the secret answer. 677 type AuthSig = EddsaSignature; 678 679 680 Keys 681 ^^^^ 682 683 .. ts:def:: SecretKeyShare 684 685 type SecretKeyShare = Cs25519Scalar; 686 687 .. ts:def:: PublicKeyShare 688 689 type PublicKeyShare = Cs25519Point; 690 691 .. ts:def:: PublicKey 692 693 type PublicKey = Cs25519Point; 694 695 .. ts:def:: SigShare 696 697 type SigShare = Cs25519Scalar; 698 699 .. ts:def:: ProviderPublicKey 700 701 type ProviderPublicKey = EddsaPublicKey; 702 703 .. ts:def:: EphemeralPublicKey 704 705 type EphemeralPublicKey = EddsaPublicKey; 706 707 .. ts:def:: EphemeralKey 708 709 type EphemeralKey = EddsaPublicKey; 710 711 .. ts:def:: AuthPub 712 713 type AuthPub = EddsaPublicKey; 714 715 Integers 716 ^^^^^^^^ 717 718 .. ts:def:: UInt8 719 720 // JavaScript numbers restricted to the range of 0-255 721 type UInt8 = number; 722 723 .. ts:def:: Identifier 724 725 // Identifier in the group 726 type Identifier = UInt8; 727 728 .. ts:def:: Threshold 729 730 type Threshold = UInt8; 731 732 .. ts:def:: NumOfParticipants 733 734 type NumOfParticipants = UInt8; 735 736 .. ts:def:: Years 737 738 type Years = number; 739 740 741 Strings 742 ^^^^^^^ 743 744 .. ts:def:: AuthMethod 745 746 type AuthMethod = string; 747 748 .. ts:def:: AuthData 749 750 type AuthData = string;