Changeset 99e37df in trunk
- Timestamp:
- 2024-08-08T21:43:51Z (8 months ago)
- Branches:
- master
- Children:
- 8fb4de0
- Parents:
- 1504bec (diff), ec7185a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 5 added
- 13 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified benchmarks/conftest.py ¶
r1504bec r99e37df 102 102 needed=number_of_nodes, 103 103 happy=number_of_nodes, 104 total=number_of_nodes ,104 total=number_of_nodes + 3, # Make sure FEC does some work 105 105 ) 106 106 ) -
TabularUnified docs/frontends/webapi.rst ¶
r1504bec r99e37df 447 447 format, as configured on the Tahoe-LAFS node responding to the request. 448 448 449 In addition, an optional "private-key=" argument is supported which, if given, 450 specifies the underlying signing key to be used when creating the directory. 451 This value must be a DER-encoded 2048-bit RSA private key in urlsafe base64 452 encoding. (To convert an existing PEM-encoded RSA key file into the format 453 required, the following commands may be used -- assuming a modern UNIX-like 454 environment with common tools already installed: 455 ``openssl rsa -in key.pem -outform der | base64 -w 0 -i - | tr '+/' '-_'``) 456 457 Because this key can be used to derive the write capability for the 458 associated directory, additional care should be taken to ensure that the key is 459 unique, that it is kept confidential, and that it was derived from an 460 appropriate (high-entropy) source of randomness. If this argument is omitted 461 (the default behavior), Tahoe-LAFS will generate an appropriate signing key 462 using the underlying operating system's source of entropy. 463 449 464 ``POST /uri?t=mkdir-with-children`` 450 465 … … 454 469 455 470 The format of the directory can be controlled with the format= argument in 456 the query string, as described above. 471 the query string and a signing key can be specified with the private-key= 472 argument, as described above. 457 473 458 474 Initial children are provided as the body of the POST form (this is more -
TabularUnified docs/proposed/index.rst ¶
r1504bec r99e37df 15 15 16 16 leasedb 17 http-storage-node-protocol -
TabularUnified docs/specifications/index.rst ¶
r1504bec r99e37df 18 18 servers-of-happiness 19 19 backends/raic 20 http-storage-node-protocol -
TabularUnified integration/test_web.py ¶
r1504bec r99e37df 13 13 14 14 import time 15 from base64 import urlsafe_b64encode 15 16 from urllib.parse import unquote as url_unquote, quote as url_quote 16 17 18 from cryptography.hazmat.primitives.serialization import load_pem_private_key 17 19 from twisted.internet.threads import deferToThread 20 from twisted.python.filepath import FilePath 18 21 19 22 import allmydata.uri 23 from allmydata.crypto.rsa import ( 24 create_signing_keypair, 25 der_string_from_signing_key, 26 PrivateKey, 27 PublicKey, 28 ) 29 from allmydata.mutable.common import derive_mutable_keys 20 30 from allmydata.util import jsonbytes as json 21 31 … … 28 38 29 39 import pytest_twisted 40 41 42 DATA_PATH = FilePath(__file__).parent().sibling("src").child("allmydata").child("test").child("data") 43 30 44 31 45 @run_in_thread … … 542 556 cap = allmydata.uri.from_string(resp) 543 557 assert isinstance(cap, allmydata.uri.DirectoryURI) 558 559 560 @run_in_thread 561 def test_mkdir_with_random_private_key(alice): 562 """ 563 Create a new directory with ?t=mkdir&private-key=... using a 564 randomly-generated RSA private key. 565 566 The writekey and fingerprint derived from the provided RSA key 567 should match those of the newly-created directory capability. 568 """ 569 570 privkey, pubkey = create_signing_keypair(2048) 571 572 writekey, _, fingerprint = derive_mutable_keys((pubkey, privkey)) 573 574 # The "private-key" parameter takes a DER-encoded RSA private key 575 # encoded in URL-safe base64; PEM blocks are not supported. 576 privkey_der = der_string_from_signing_key(privkey) 577 privkey_encoded = urlsafe_b64encode(privkey_der).decode("ascii") 578 579 resp = util.web_post( 580 alice.process, u"uri", 581 params={ 582 u"t": "mkdir", 583 u"private-key": privkey_encoded, 584 }, 585 ) 586 assert resp.startswith(b"URI:DIR2") 587 588 dircap = allmydata.uri.from_string(resp) 589 assert isinstance(dircap, allmydata.uri.DirectoryURI) 590 591 # DirectoryURI objects lack 'writekey' and 'fingerprint' attributes 592 # so extract them from the enclosed WriteableSSKFileURI object. 593 filecap = dircap.get_filenode_cap() 594 assert isinstance(filecap, allmydata.uri.WriteableSSKFileURI) 595 596 assert (writekey, fingerprint) == (filecap.writekey, filecap.fingerprint) 597 598 599 @run_in_thread 600 def test_mkdir_with_known_private_key(alice): 601 """ 602 Create a new directory with ?t=mkdir&private-key=... using a 603 known-in-advance RSA private key. 604 605 The writekey and fingerprint derived from the provided RSA key 606 should match those of the newly-created directory capability. 607 In addition, because the writekey and fingerprint are derived 608 deterministically, given the same RSA private key, the resultant 609 directory capability should always be the same. 610 """ 611 # Generated with `openssl genrsa -out openssl-rsa-2048-3.txt 2048` 612 pempath = DATA_PATH.child("openssl-rsa-2048-3.txt") 613 privkey = load_pem_private_key(pempath.getContent(), password=None) 614 assert isinstance(privkey, PrivateKey) 615 pubkey = privkey.public_key() 616 assert isinstance(pubkey, PublicKey) 617 618 writekey, _, fingerprint = derive_mutable_keys((pubkey, privkey)) 619 620 # The "private-key" parameter takes a DER-encoded RSA private key 621 # encoded in URL-safe base64; PEM blocks are not supported. 622 privkey_der = der_string_from_signing_key(privkey) 623 privkey_encoded = urlsafe_b64encode(privkey_der).decode("ascii") 624 625 resp = util.web_post( 626 alice.process, u"uri", 627 params={ 628 u"t": "mkdir", 629 u"private-key": privkey_encoded, 630 }, 631 ) 632 assert resp.startswith(b"URI:DIR2") 633 634 dircap = allmydata.uri.from_string(resp) 635 assert isinstance(dircap, allmydata.uri.DirectoryURI) 636 637 # DirectoryURI objects lack 'writekey' and 'fingerprint' attributes 638 # so extract them from the enclosed WriteableSSKFileURI object. 639 filecap = dircap.get_filenode_cap() 640 assert isinstance(filecap, allmydata.uri.WriteableSSKFileURI) 641 642 assert (writekey, fingerprint) == (filecap.writekey, filecap.fingerprint) 643 644 assert resp == b"URI:DIR2:3oo7j7f7qqxnet2z2lf57ucup4:cpktmsxlqnd5yeekytxjxvff5e6d6fv7py6rftugcndvss7tzd2a" 645 646 647 @run_in_thread 648 def test_mkdir_with_children_and_random_private_key(alice): 649 """ 650 Create a new directory with ?t=mkdir-with-children&private-key=... 651 using a randomly-generated RSA private key. 652 653 The writekey and fingerprint derived from the provided RSA key 654 should match those of the newly-created directory capability. 655 """ 656 657 # create a file to put in our directory 658 FILE_CONTENTS = u"some file contents\n" * 500 659 resp = requests.put( 660 util.node_url(alice.process.node_dir, u"uri"), 661 data=FILE_CONTENTS, 662 ) 663 filecap = resp.content.strip() 664 665 # create a (sub) directory to put in our directory 666 resp = requests.post( 667 util.node_url(alice.process.node_dir, u"uri"), 668 params={ 669 u"t": u"mkdir", 670 } 671 ) 672 # (we need both the read-write and read-only URIs I guess) 673 dircap = resp.content 674 dircap_obj = allmydata.uri.from_string(dircap) 675 dircap_ro = dircap_obj.get_readonly().to_string() 676 677 # create json information about our directory 678 meta = { 679 "a_file": [ 680 "filenode", { 681 "ro_uri": filecap, 682 "metadata": { 683 "ctime": 1202777696.7564139, 684 "mtime": 1202777696.7564139, 685 "tahoe": { 686 "linkcrtime": 1202777696.7564139, 687 "linkmotime": 1202777696.7564139 688 } 689 } 690 } 691 ], 692 "some_subdir": [ 693 "dirnode", { 694 "rw_uri": dircap, 695 "ro_uri": dircap_ro, 696 "metadata": { 697 "ctime": 1202778102.7589991, 698 "mtime": 1202778111.2160511, 699 "tahoe": { 700 "linkcrtime": 1202777696.7564139, 701 "linkmotime": 1202777696.7564139 702 } 703 } 704 } 705 ] 706 } 707 708 privkey, pubkey = create_signing_keypair(2048) 709 710 writekey, _, fingerprint = derive_mutable_keys((pubkey, privkey)) 711 712 # The "private-key" parameter takes a DER-encoded RSA private key 713 # encoded in URL-safe base64; PEM blocks are not supported. 714 privkey_der = der_string_from_signing_key(privkey) 715 privkey_encoded = urlsafe_b64encode(privkey_der).decode("ascii") 716 717 # create a new directory with one file and one sub-dir (all-at-once) 718 # with the supplied RSA private key 719 resp = util.web_post( 720 alice.process, u"uri", 721 params={ 722 u"t": "mkdir-with-children", 723 u"private-key": privkey_encoded, 724 }, 725 data=json.dumps(meta), 726 ) 727 assert resp.startswith(b"URI:DIR2") 728 729 dircap = allmydata.uri.from_string(resp) 730 assert isinstance(dircap, allmydata.uri.DirectoryURI) 731 732 # DirectoryURI objects lack 'writekey' and 'fingerprint' attributes 733 # so extract them from the enclosed WriteableSSKFileURI object. 734 filecap = dircap.get_filenode_cap() 735 assert isinstance(filecap, allmydata.uri.WriteableSSKFileURI) 736 737 assert (writekey, fingerprint) == (filecap.writekey, filecap.fingerprint) 738 739 740 @run_in_thread 741 def test_mkdir_with_children_and_known_private_key(alice): 742 """ 743 Create a new directory with ?t=mkdir-with-children&private-key=... 744 using a known-in-advance RSA private key. 745 746 747 The writekey and fingerprint derived from the provided RSA key 748 should match those of the newly-created directory capability. 749 In addition, because the writekey and fingerprint are derived 750 deterministically, given the same RSA private key, the resultant 751 directory capability should always be the same. 752 """ 753 754 # create a file to put in our directory 755 FILE_CONTENTS = u"some file contents\n" * 500 756 resp = requests.put( 757 util.node_url(alice.process.node_dir, u"uri"), 758 data=FILE_CONTENTS, 759 ) 760 filecap = resp.content.strip() 761 762 # create a (sub) directory to put in our directory 763 resp = requests.post( 764 util.node_url(alice.process.node_dir, u"uri"), 765 params={ 766 u"t": u"mkdir", 767 } 768 ) 769 # (we need both the read-write and read-only URIs I guess) 770 dircap = resp.content 771 dircap_obj = allmydata.uri.from_string(dircap) 772 dircap_ro = dircap_obj.get_readonly().to_string() 773 774 # create json information about our directory 775 meta = { 776 "a_file": [ 777 "filenode", { 778 "ro_uri": filecap, 779 "metadata": { 780 "ctime": 1202777696.7564139, 781 "mtime": 1202777696.7564139, 782 "tahoe": { 783 "linkcrtime": 1202777696.7564139, 784 "linkmotime": 1202777696.7564139 785 } 786 } 787 } 788 ], 789 "some_subdir": [ 790 "dirnode", { 791 "rw_uri": dircap, 792 "ro_uri": dircap_ro, 793 "metadata": { 794 "ctime": 1202778102.7589991, 795 "mtime": 1202778111.2160511, 796 "tahoe": { 797 "linkcrtime": 1202777696.7564139, 798 "linkmotime": 1202777696.7564139 799 } 800 } 801 } 802 ] 803 } 804 805 # Generated with `openssl genrsa -out openssl-rsa-2048-4.txt 2048` 806 pempath = DATA_PATH.child("openssl-rsa-2048-4.txt") 807 privkey = load_pem_private_key(pempath.getContent(), password=None) 808 assert isinstance(privkey, PrivateKey) 809 pubkey = privkey.public_key() 810 assert isinstance(pubkey, PublicKey) 811 812 writekey, _, fingerprint = derive_mutable_keys((pubkey, privkey)) 813 814 # The "private-key" parameter takes a DER-encoded RSA private key 815 # encoded in URL-safe base64; PEM blocks are not supported. 816 privkey_der = der_string_from_signing_key(privkey) 817 privkey_encoded = urlsafe_b64encode(privkey_der).decode("ascii") 818 819 # create a new directory with one file and one sub-dir (all-at-once) 820 # with the supplied RSA private key 821 resp = util.web_post( 822 alice.process, u"uri", 823 params={ 824 u"t": "mkdir-with-children", 825 u"private-key": privkey_encoded, 826 }, 827 data=json.dumps(meta), 828 ) 829 assert resp.startswith(b"URI:DIR2") 830 831 dircap = allmydata.uri.from_string(resp) 832 assert isinstance(dircap, allmydata.uri.DirectoryURI) 833 834 # DirectoryURI objects lack 'writekey' and 'fingerprint' attributes 835 # so extract them from the enclosed WriteableSSKFileURI object. 836 filecap = dircap.get_filenode_cap() 837 assert isinstance(filecap, allmydata.uri.WriteableSSKFileURI) 838 839 assert (writekey, fingerprint) == (filecap.writekey, filecap.fingerprint) 840 841 assert resp == b"URI:DIR2:ppwzpwrd37xi7tpribxyaa25uy:imdws47wwpzfkc5vfllo4ugspb36iit4cqps6ttuhaouc66jb2da" -
TabularUnified src/allmydata/client.py ¶
r1504bec r99e37df 33 33 from allmydata.crypto import rsa, ed25519 34 34 from allmydata.crypto.util import remove_prefix 35 from allmydata.dirnode import DirectoryNode 35 36 from allmydata.storage.server import StorageServer, FoolscapStorageServer 36 37 from allmydata import storage_client … … 1126 1127 return self.nodemaker.create_from_cap(write_uri, read_uri, deep_immutable=deep_immutable, name=name) 1127 1128 1128 def create_dirnode(self, initial_children=None, version=None): 1129 d = self.nodemaker.create_new_mutable_directory(initial_children, version=version) 1129 def create_dirnode( 1130 self, 1131 initial_children: dict | None = None, 1132 version: int | None = None, 1133 *, 1134 unique_keypair: tuple[rsa.PublicKey, rsa.PrivateKey] | None = None 1135 ) -> DirectoryNode: 1136 """ 1137 Create a new directory. 1138 1139 :param initial_children: If given, a structured dict representing the 1140 initial content of the created directory. See 1141 `docs/frontends/webapi.rst` for examples. 1142 1143 :param version: If given, an int representing the mutable file format 1144 of the new object. Acceptable values are currently `SDMF_VERSION` 1145 or `MDMF_VERSION` (corresponding to 0 or 1, respectively, as 1146 defined in `allmydata.interfaces`). If no such value is provided, 1147 the default mutable format will be used (currently SDMF). 1148 1149 :param unique_keypair: an optional tuple containing the RSA public 1150 and private key to be used for the new directory. Typically, this 1151 value is omitted (in which case a new random keypair will be 1152 generated at creation time). 1153 1154 **Warning** This value independently determines the identity of 1155 the mutable object to create. There cannot be two different 1156 mutable objects that share a keypair. They will merge into one 1157 object (with undefined contents). 1158 1159 :return: A Deferred which will fire with a representation of the new 1160 directory after it has been created. 1161 """ 1162 d = self.nodemaker.create_new_mutable_directory( 1163 initial_children, 1164 version=version, 1165 keypair=unique_keypair, 1166 ) 1130 1167 return d 1131 1168 -
TabularUnified src/allmydata/crypto/aes.py ¶
r1504bec r99e37df 78 78 79 79 _validate_cryptor(encryptor, encrypt=True) 80 if not isinstance(plaintext, bytes):81 raise ValueError( 'Plaintext must be bytes')80 if not isinstance(plaintext, (bytes, memoryview)): 81 raise ValueError(f'Plaintext must be bytes or memoryview: {type(plaintext)}') 82 82 83 83 return encryptor.update(plaintext) … … 117 117 118 118 _validate_cryptor(decryptor, encrypt=False) 119 if not isinstance(plaintext, bytes):120 raise ValueError( 'Plaintext must be bytes')119 if not isinstance(plaintext, (bytes, memoryview)): 120 raise ValueError(f'Plaintext must be bytes or memoryview: {type(plaintext)}') 121 121 122 122 return decryptor.update(plaintext) -
TabularUnified src/allmydata/immutable/downloader/node.py ¶
r1504bec r99e37df 412 412 def process_blocks(self, segnum, blocks): 413 413 start = now() 414 d = defer.maybeDeferred(self._decode_blocks,segnum, blocks)414 d = self._decode_blocks(segnum, blocks) 415 415 d.addCallback(self._check_ciphertext_hash, segnum) 416 416 def _deliver(result): -
TabularUnified src/allmydata/mutable/filenode.py ¶
r1504bec r99e37df 15 15 from allmydata.util import hashutil, log, consumer, deferredutil, mathutil 16 16 from allmydata.util.assertutil import precondition 17 from allmydata.util.cputhreadpool import defer_to_thread 17 18 from allmydata.uri import WriteableSSKFileURI, ReadonlySSKFileURI, \ 18 19 WriteableMDMFFileURI, ReadonlyMDMFFileURI … … 129 130 return self 130 131 131 def create_with_keys(self, keypair, contents, 132 @deferredutil.async_to_deferred 133 async def create_with_keys(self, keypair, contents, 132 134 version=SDMF_VERSION): 133 135 """Call this to create a brand-new mutable file. It will create the … … 138 140 """ 139 141 self._pubkey, self._privkey = keypair 140 self._writekey, self._encprivkey, self._fingerprint = derive_mutable_keys(141 keypair,142 self._writekey, self._encprivkey, self._fingerprint = await defer_to_thread( 143 derive_mutable_keys, keypair 142 144 ) 143 145 if version == MDMF_VERSION: … … 150 152 self._storage_index = self._uri.storage_index 151 153 initial_contents = self._get_initial_contents(contents) 152 return self._upload(initial_contents, None)154 return await self._upload(initial_contents, None) 153 155 154 156 def _get_initial_contents(self, contents): -
TabularUnified src/allmydata/mutable/retrieve.py ¶
r1504bec r99e37df 5 5 6 6 import time 7 8 7 from itertools import count 8 9 9 from zope.interface import implementer 10 10 from twisted.internet import defer … … 874 874 self.log("decoding segment %d" % segnum) 875 875 if segnum == self._num_segments - 1: 876 d = defer.maybeDeferred(self._tail_decoder.decode, shares, shareids) 877 else: 878 d = defer.maybeDeferred(self._segment_decoder.decode, shares, shareids) 879 def _process(buffers): 880 segment = b"".join(buffers) 876 d = self._tail_decoder.decode(shares, shareids) 877 else: 878 d = self._segment_decoder.decode(shares, shareids) 879 880 # For larger shares, this can take a few milliseconds. As such, we want 881 # to unblock the event loop. In newer Python b"".join() will release 882 # the GIL: https://github.com/python/cpython/issues/80232 883 @deferredutil.async_to_deferred 884 async def _got_buffers(buffers): 885 return await defer_to_thread(lambda: b"".join(buffers)) 886 887 d.addCallback(_got_buffers) 888 889 def _process(segment): 881 890 self.log(format="now decoding segment %(segnum)s of %(numsegs)s", 882 891 segnum=segnum, … … 929 938 ) 930 939 931 932 def _try_to_validate_privkey(self, enc_privkey, reader, server):940 @deferredutil.async_to_deferred 941 async def _try_to_validate_privkey(self, enc_privkey, reader, server): 933 942 node_writekey = self._node.get_writekey() 934 alleged_privkey_s = decrypt_privkey(node_writekey, enc_privkey) 935 alleged_writekey = hashutil.ssk_writekey_hash(alleged_privkey_s) 936 if alleged_writekey != node_writekey: 943 944 def get_privkey(): 945 alleged_privkey_s = decrypt_privkey(node_writekey, enc_privkey) 946 alleged_writekey = hashutil.ssk_writekey_hash(alleged_privkey_s) 947 if alleged_writekey != node_writekey: 948 return None 949 privkey, _ = rsa.create_signing_keypair_from_string(alleged_privkey_s) 950 return privkey 951 952 privkey = await defer_to_thread(get_privkey) 953 if privkey is None: 937 954 self.log("invalid privkey from %s shnum %d" % 938 955 (reader, reader.shnum), … … 951 968 self.log("got valid privkey from shnum %d on reader %s" % 952 969 (reader.shnum, reader)) 953 privkey, _ = rsa.create_signing_keypair_from_string(alleged_privkey_s)954 970 self._node._populate_encprivkey(enc_privkey) 955 971 self._node._populate_privkey(privkey) -
TabularUnified src/allmydata/nodemaker.py ¶
r1504bec r99e37df 136 136 return d 137 137 138 def create_new_mutable_directory(self, initial_children=None, version=None): 138 def create_new_mutable_directory( 139 self, 140 initial_children=None, 141 version=None, 142 *, 143 keypair: tuple[PublicKey, PrivateKey] | None = None, 144 ): 139 145 if initial_children is None: 140 146 initial_children = {} … … 146 152 MutableData(pack_children(initial_children, 147 153 n.get_writekey())), 148 version=version) 154 version=version, 155 keypair=keypair) 149 156 d.addCallback(self._create_dirnode) 150 157 return d -
TabularUnified src/allmydata/test/test_dirnode.py ¶
r1504bec r99e37df 10 10 from twisted.internet import defer 11 11 from twisted.internet.interfaces import IConsumer 12 from twisted.python.filepath import FilePath 12 13 from allmydata import uri, dirnode 13 14 from allmydata.client import _Client 15 from allmydata.crypto.rsa import create_signing_keypair 14 16 from allmydata.immutable import upload 15 17 from allmydata.immutable.literal import LiteralFileNode … … 20 22 MDMF_VERSION, SDMF_VERSION 21 23 from allmydata.mutable.filenode import MutableFileNode 22 from allmydata.mutable.common import UncoordinatedWriteError 24 from allmydata.mutable.common import ( 25 UncoordinatedWriteError, 26 derive_mutable_keys, 27 ) 23 28 from allmydata.util import hashutil, base32 24 29 from allmydata.util.netstring import split_netstring … … 26 31 from allmydata.test.common import make_chk_file_uri, make_mutable_file_uri, \ 27 32 ErrorMixin 33 from allmydata.test.mutable.util import ( 34 FakeStorage, 35 make_nodemaker_with_peers, 36 make_peer, 37 ) 28 38 from allmydata.test.no_network import GridTestMixin 29 39 from allmydata.unknown import UnknownNode, strip_prefix_for_ro 30 40 from allmydata.nodemaker import NodeMaker 31 41 from base64 import b32decode 42 from cryptography.hazmat.primitives.serialization import load_pem_private_key 32 43 import allmydata.test.common_util as testutil 33 44 … … 1979 1990 d.addCallback(_test_adder) 1980 1991 return d 1992 1993 1994 class DeterministicDirnode(testutil.ReallyEqualMixin, testutil.ShouldFailMixin, unittest.TestCase): 1995 def setUp(self): 1996 # Copied from allmydata.test.mutable.test_filenode 1997 super(DeterministicDirnode, self).setUp() 1998 self._storage = FakeStorage() 1999 self._peers = list( 2000 make_peer(self._storage, n) 2001 for n 2002 in range(10) 2003 ) 2004 self.nodemaker = make_nodemaker_with_peers(self._peers) 2005 2006 async def test_create_with_random_keypair(self): 2007 """ 2008 Create a dirnode using a random RSA keypair. 2009 2010 The writekey and fingerprint of the enclosed mutable filecap 2011 should match those derived from the given keypair. 2012 """ 2013 privkey, pubkey = create_signing_keypair(2048) 2014 writekey, _, fingerprint = derive_mutable_keys((pubkey, privkey)) 2015 2016 node = await self.nodemaker.create_new_mutable_directory( 2017 keypair=(pubkey, privkey) 2018 ) 2019 self.failUnless(isinstance(node, dirnode.DirectoryNode)) 2020 2021 dircap = uri.from_string(node.get_uri()) 2022 self.failUnless(isinstance(dircap, uri.DirectoryURI)) 2023 2024 filecap = dircap.get_filenode_cap() 2025 self.failUnless(isinstance(filecap, uri.WriteableSSKFileURI)) 2026 2027 self.failUnlessReallyEqual(filecap.writekey, writekey) 2028 self.failUnlessReallyEqual(filecap.fingerprint, fingerprint) 2029 2030 async def test_create_with_known_keypair(self): 2031 """ 2032 Create a dirnode using a known RSA keypair. 2033 2034 The writekey and fingerprint of the enclosed mutable filecap 2035 should match those derived from the given keypair. Because 2036 these values are derived deterministically, given the same 2037 keypair, the resulting filecap should also always be the same. 2038 """ 2039 # Generated with `openssl genrsa -out openssl-rsa-2048-2.txt 2048` 2040 pempath = FilePath(__file__).sibling("data").child("openssl-rsa-2048-2.txt") 2041 privkey = load_pem_private_key(pempath.getContent(), password=None) 2042 pubkey = privkey.public_key() 2043 writekey, _, fingerprint = derive_mutable_keys((pubkey, privkey)) 2044 2045 node = await self.nodemaker.create_new_mutable_directory( 2046 keypair=(pubkey, privkey) 2047 ) 2048 self.failUnless(isinstance(node, dirnode.DirectoryNode)) 2049 2050 dircap = uri.from_string(node.get_uri()) 2051 self.failUnless(isinstance(dircap, uri.DirectoryURI)) 2052 2053 filecap = dircap.get_filenode_cap() 2054 self.failUnless(isinstance(filecap, uri.WriteableSSKFileURI)) 2055 2056 self.failUnlessReallyEqual(filecap.writekey, writekey) 2057 self.failUnlessReallyEqual(filecap.fingerprint, fingerprint) 2058 2059 self.failUnlessReallyEqual( 2060 # Despite being named "to_string", this actually returns bytes.. 2061 dircap.to_string(), 2062 b'URI:DIR2:n4opqgewgcn4mddu4oiippaxru:ukpe4z6xdlujdpguoabergyih3bj7iaafukdqzwthy2ytdd5bs2a' 2063 ) -
TabularUnified src/allmydata/web/unlinked.py ¶
r1504bec r99e37df 161 161 if file_format: 162 162 mt = get_mutable_type(file_format) 163 d = client.create_dirnode(version=mt )163 d = client.create_dirnode(version=mt, unique_keypair=get_keypair(req)) 164 164 redirect = get_arg(req, "redirect_to_result", "false") 165 165 if boolean_of_arg(redirect): … … 179 179 kids_json = req.content.read() 180 180 kids = convert_children_json(client.nodemaker, kids_json) 181 d = client.create_dirnode(initial_children=kids )181 d = client.create_dirnode(initial_children=kids, unique_keypair=get_keypair(req)) 182 182 redirect = get_arg(req, "redirect_to_result", "false") 183 183 if boolean_of_arg(redirect):
Note: See TracChangeset
for help on using the changeset viewer.