Ejemplo n.º 1
0
def stamp_command(fd, args):
    # Create initial commitment ops for all files
    merkle_roots = []

    try:
        file_timestamp = DetachedTimestampFile.from_fd(OpSHA256(), fd)
    except OSError as exp:
        logging.error("Could not read %r: %s" % (fd.name, exp))
        return

    # Add nonce
    nonce_appended_stamp = file_timestamp.timestamp.ops.add(
        OpAppend(os.urandom(16)))
    merkle_root = nonce_appended_stamp.ops.add(OpSHA256())
    merkle_roots.append(merkle_root)
    merkle_tip = make_merkle_tree(merkle_roots)

    create_timestamp(merkle_tip, CALENDAR_URLS, parse_ots_args(args))

    try:
        with open("%s.ots" % fd.name, "wb") as timestamp_fd:
            ctx = StreamSerializationContext(timestamp_fd)
            file_timestamp.serialize(ctx)
    except IOError as exp:
        logger.error("Failed to create timestamp: %s" % exp)
        return
Ejemplo n.º 2
0
def cat_then_unary_op(unary_op_cls, left, right):
    """Concatenate left and right, then perform a unary operation on them

    left and right can be either timestamps or bytes.

    Appropriate intermediary append/prepend operations will be created as
    needed for left and right.
    """
    if not isinstance(left, Timestamp):
        left = Timestamp(left)

    if not isinstance(right, Timestamp):
        right = Timestamp(right)

    left_append_stamp = left.ops.add(OpAppend(right.msg))
    right_prepend_stamp = right.ops.add(OpPrepend(left.msg))

    # Left and right should produce the same thing, so we can set the timestamp
    # of the left to the right.
    left.ops[OpAppend(right.msg)] = right_prepend_stamp

    return right_prepend_stamp.ops.add(unary_op_cls())
Ejemplo n.º 3
0
    def submit(self, submitted_commitment):
        idx = int(time.time())

        serialized_idx = struct.pack('>L', idx)

        commitment = submitted_commitment.ops.add(OpPrepend(serialized_idx))

        per_idx_key = derive_key_for_idx(self.hmac_key, idx, bits=32)
        mac = hashlib.sha256(commitment.msg + per_idx_key).digest()[0:HMAC_SIZE]
        macced_commitment = commitment.ops.add(OpAppend(mac))

        macced_commitment.attestations.add(PendingAttestation(self.uri))
        self.journal.submit(macced_commitment.msg)
Ejemplo n.º 4
0
 def upgrade_timestamps_tx(self, tx):
     for category, script, amount in tx.outputs():
         if category == 2:  # agt -> txid
             agt = script[4:]  # drop "6a20" op_return and op_pushdata(32)
             tx_raw = tx.serialize(witness=False)
             if len(x(tx_raw)) <= Op.MAX_MSG_LENGTH:
                 i = tx_raw.find(agt)
                 prepend = x(tx_raw[:i])
                 append = x(tx_raw[i + len(agt):])
                 t_agt = Timestamp(x(agt))
                 t = t_agt.ops.add(OpPrepend(prepend))
                 t = t.ops.add(OpAppend(append))
                 t = t.ops.add(OpSHA256())
                 t = t.ops.add(OpSHA256())  # txid in little endian
                 for f in self.proofs_storage_file.incomplete_proofs:
                     tf = roll_timestamp(f.detached_timestamp.timestamp)
                     if tf.msg == x(agt):
                         tf.merge(t_agt)
                         f.status = "pending"
                         f.txid = t.msg[::-1].hex()
     self.update_storage()
Ejemplo n.º 5
0
def generate(msg_bytes):
    '''Generates certificate'''

    hashed_bytes = hashlib.new('sha256', msg_bytes).digest()
    file_timestamp = DetachedTimestampFile(OpSHA256(), Timestamp(hashed_bytes))

    nonce_appended_stamp = file_timestamp.timestamp.ops.add(OpAppend(os.urandom(16)))
    timestamp = nonce_appended_stamp.ops.add(OpSHA256())

    remote_calendar = RemoteCalendar(CALENDAR_URL)

    result = remote_calendar.submit(timestamp.msg, timeout=None)

    try:
        if isinstance(result, Timestamp):
            timestamp.merge(result)
        else:
            logging.debug(str(result))
    except Exception as error:
        logging.debug(str(error))

    return file_timestamp
Ejemplo n.º 6
0
def main():
    parser = otsclient.args.make_common_options_arg_parser()

    parser.add_argument("-g",
                        "--gpg-program",
                        action="store",
                        default="/usr/bin/gpg",
                        help="Path to the GnuPG binary (default %(default)s)")

    parser.add_argument(
        '-c',
        '--calendar',
        metavar='URL',
        dest='calendar_urls',
        action='append',
        type=str,
        default=[
            "https://calendar.bitmark.one",
            "https://a.pool.opentimestamps.org",
            "https://b.pool.opentimestamps.org",
            "https://a.pool.eternitywall.com", "https://ots.btc.catallaxy.com"
        ],
        help=
        'Create timestamp with the aid of a remote calendar. May be specified multiple times. Default: %(default)r'
    )
    parser.add_argument(
        '-b',
        '--btc-wallet',
        dest='use_btc_wallet',
        action='store_true',
        help='Create timestamp locally with the local Bitcoin wallet.')
    parser.add_argument("gpgargs",
                        nargs=argparse.REMAINDER,
                        help='Arguments passed to GnuPG binary')

    parser.add_argument("--timeout",
                        type=int,
                        default=5,
                        help="Timeout before giving up on a calendar. "
                        "Default: %(default)d")

    parser.add_argument("-m",
                        type=int,
                        default="2",
                        help="Commitments are sent to remote calendars,"
                        "in the event of timeout the timestamp is considered "
                        "done if at least M calendars replied. "
                        "Default: %(default)s")

    parser.add_argument('--rehash-trees',
                        action='store_true',
                        help=argparse.SUPPRESS)

    args = otsclient.args.handle_common_options(parser.parse_args(), parser)

    logging.basicConfig(format='ots: %(message)s')

    args.verbosity = args.verbose - args.quiet
    if args.verbosity == 0:
        logging.root.setLevel(logging.INFO)
    elif args.verbosity > 0:
        logging.root.setLevel(logging.DEBUG)
    elif args.verbosity == -1:
        logging.root.setLevel(logging.WARNING)
    elif args.verbosity < -1:
        logging.root.setLevel(logging.ERROR)

    if len(args.gpgargs) == 0 or args.gpgargs[0] != '--':
        parser.error("You need to have '--' as the last argument; see docs")

    args.gpgargs = args.gpgargs[1:]

    parser = argparse.ArgumentParser()
    parser.add_argument("-bsau", action="store")
    parser.add_argument("--verify", action="store")
    gpgargs = parser.parse_known_args(args.gpgargs)[0]

    if gpgargs.bsau:
        with subprocess.Popen([args.gpg_program] + args.gpgargs,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE) as gpg_proc:
            logging.debug("Reading Git commit")
            git_commit = sys.stdin.buffer.read()

            logging.debug("Git commit: %r" % git_commit)

            # FIXME: can this fail to write all bytes?
            n = gpg_proc.stdin.write(git_commit)
            logging.debug("Wrote %d bytes to GnuPG out of %d" %
                          (n, len(git_commit)))
            gpg_proc.stdin.close()

            gpg_sig = gpg_proc.stdout.read()

            # GnuPG produces no output on failure
            if not gpg_sig:
                sys.exit(1)

            logging.debug("PGP sig: %r" % gpg_sig)

            # Timestamp the commit and tag together
            signed_commit_timestamp = Timestamp(
                hash_signed_commit(git_commit, gpg_sig))
            final_timestamp = signed_commit_timestamp

            # with git tree rehashing
            minor_version = 1

            # CWD will be the git repo, so this should get us the right one
            repo = git.Repo()

            hextree_start = None
            if git_commit.startswith(b'tree '):
                hextree_start = 5
            elif git_commit.startswith(b'object '):
                # I believe this is always a git tag
                hextree_start = 7
            else:
                raise AssertionError("Don't know what to do with %r" %
                                     git_commit)

            hextree = git_commit[hextree_start:hextree_start + 20 * 2].decode()
            tree = repo.tree(hextree)
            tree.path = ''

            tree_stamper = GitTreeTimestamper(tree)

            final_timestamp = signed_commit_timestamp.ops.add(
                OpAppend(tree_stamper.timestamp.msg)).ops.add(OpSHA256())

            otsclient.cmds.create_timestamp(final_timestamp,
                                            args.calendar_urls, args)

            if args.wait:
                # Interpreted as override by the upgrade command
                # FIXME: need to clean this bad abstraction up!
                args.calendar_urls = []
                otsclient.cmds.upgrade_timestamp(signed_commit_timestamp, args)

            sys.stdout.buffer.write(gpg_sig)
            write_ascii_armored(signed_commit_timestamp, sys.stdout.buffer,
                                minor_version)

    elif gpgargs.verify:
        # Verify
        with open(gpgargs.verify, 'rb') as gpg_sig_fd:
            gpg_sig = gpg_sig_fd.read()
            git_commit = sys.stdin.buffer.read()

            (major_version, minor_version,
             timestamp) = deserialize_ascii_armored_timestamp(
                 git_commit, gpg_sig)
            if timestamp is None:
                print("OpenTimestamps: No timestamp found", file=sys.stderr)
            else:
                good = otsclient.cmds.verify_timestamp(timestamp, args)

                if good:
                    logging.info("Good timestamp")
                else:
                    logging.warning("Could not verify timestamp!")
            sys.stderr.flush()

            logging.debug("Running GnuPG binary: %r" %
                          ([args.gpg_program] + args.gpgargs))
            with subprocess.Popen([args.gpg_program] + args.gpgargs,
                                  stdin=subprocess.PIPE) as gpg_proc:
                gpg_proc.stdin.write(git_commit)
                gpg_proc.stdin.close()
Ejemplo n.º 7
0
def make_timestamp_from_block(digest, block, blockheight, *, max_tx_size=1000):
    state = make_trie(block)
    my_root = state.root_hash
    block_root = bytes.fromhex(block['transactionsRoot'][2:])
    assert my_root == block_root

    try:
        j, prepend_tx, append_tx = found_tx(digest, block, max_tx_size)
    except ValueError:
        return None
    tx_raw = prepend_tx + digest + append_tx
    # print("tx_raw: " + tx_raw)
    # print("tx_hash: " + sha3.keccak_256(bytes.fromhex(tx_raw)).hexdigest())

    rlp_encode = rlp.encode(j)
    # print("rlp_encode: " + bytes.hex(rlp_encode))
    nibbles = trie.bin_to_nibbles(rlp_encode)
    current_node = state.root_node
    ops_list = []
    nibble_iter = nibbles.__iter__()

    while True:
        node_type = state._get_node_type(current_node)
        # print("node type: " + str(node_type))
        # print([bytes.hex(cur_el) for cur_el in current_node])
        current_node_rlp = rlp.encode(current_node)
        current_node_encoded = bytes.hex(current_node_rlp)
        # print(current_node_encoded)
        try:
            index = next(nibble_iter)
        except:
            pass

        current_el = current_node[index if node_type == trie.NODE_TYPE_BRANCH else 1]
        current_el_hex = bytes.hex(current_el)
        # print(str(index) + ":" + current_el_hex)
        [prepend, append] = get_append_and_prepend(current_el_hex, current_node_encoded)

        ops_list.append(OpKECCAK256())
        if len(append) > 0:
            ops_list.append(OpAppend(bytes.fromhex(append)))
        if len(prepend) > 0:
            ops_list.append(OpPrepend(bytes.fromhex(prepend)))

        if node_type == trie.NODE_TYPE_LEAF:
            break
        else:
            current_node = state._decode_to_node(current_el)

    assert tx_raw == prepend_tx + digest + append_tx
    orig = Timestamp(bytes.fromhex(digest))
    current = orig
    if len(prepend_tx) > 0:
        current = current.ops.add(OpPrepend(bytes.fromhex(prepend_tx)))
    if len(append_tx) > 0:
        current = current.ops.add(OpAppend(bytes.fromhex(append_tx)))
    while len(ops_list) > 0:
        current = current.ops.add(ops_list.pop())
    attestation = EthereumBlockHeaderAttestation(blockheight)
    current.attestations.add(attestation)

    return orig
Ejemplo n.º 8
0
def nonce_timestamp(private_timestamp, crypt_op=OpSHA256(), length=16):
    """Create a nonced version of a timestamp for privacy"""
    stamp2 = private_timestamp.ops.add(OpAppend(os.urandom(length)))
    return stamp2.ops.add(crypt_op)