Ejemplo n.º 1
0
def generateHSDesc(replica):
    """Generate a ``@type rendezvous-service-descriptor`` for an Hidden
    Service.

    .. todo:: Make generation of ``permanent_ids`` deal with HS "stealth"
        authorisation.
    .. todo:: Implement per-client ``session_keys`` and
        ``descriptor_cookies``, see rend-spec.txt §2.1.

    :param int replica: The ``replica`` number for this particular descriptor.
        This influences the ``secret-id-part`` of the descriptor (see
        :func:`~leekspin.rendezvous.calculateSecretIDPart`).
    :rtype: str
    :returns: A ``@type rendezvous-service-descriptor`` as a string.
    """
    import time

    vers = torversions.getRandomVersion()
    versionsLine = rendezvous.generateVersionLine(vers)
    protocolVersionsLine = rendezvous.generateProtocolVersionsLine(vers)

    (secretPermanentKey,
     publicPermanentKey,
     permanentKeyLine) = rendezvous.generatePermanentKey()

    (secretSigningKey,
     publicSigningKey,
     signingKeyLine) = crypto.generateSigningKey()

    # TODO: Make generation of permanent_ids deal with HS "stealth" authorisation.
    permanentID = rendezvous.generatePermanentID(publicPermanentKey)

    # TODO: Implement per-client session-keys / descriptor cookies, see
    #       rend-spec.txt §2.1.
    descCookie = rendezvous.createDescriptorCookie()
    descCookieB64 = base64.b64encode(descCookie)#.strip("=")
    # see rendclient.c rend_parse_service_authorization()↑↑↑

    logging.info(("# Generated HS .onion address: %s\n"
                  "# Generated HS descriptor cookie: %s") %
                 (permanentID.encode("hex") + ".onion", descCookieB64))

    currentTime = int(time.time())
    publicationTimeLine = rendezvous.generatePublicationTimeLine(currentTime)
    (secretIDPart,
     secretIDLine) = rendezvous.calculateSecretIDPart(permanentID, currentTime,
                                                      descCookieB64, replica)
    introductionPoints = rendezvous.generateIntroPoints(descCookieB64)
    rendServiceLine = rendezvous.generateRendServiceLine(permanentID,
                                                         secretIDPart, replica)
    d = []
    d.append(rendServiceLine)
    d.append(versionsLine)
    d.append(permanentKeyLine)
    d.append(secretIDLine)
    d.append(publicationTimeLine)
    d.append(protocolVersionsLine)
    d.append(introductionPoints)
    d.append(const.TOKEN_HS_SIGNATURE)

    document = "\r\n".join(d) + "\r\n"
    (_, _, documentDigestPKCS1) = crypto.digestDescriptorContent(document)
    descriptor = crypto.signDescriptorContent(document, secretSigningKey,
                                              token=const.TOKEN_HS_SIGNATURE)
    # "router-signature" is for relay/bridge descriptor signatures; we have to
    # replace it with just "signature":
    descriptor = descriptor.replace("router-signature", "signature")
    logging.info("%s\n" % descriptor)

    return descriptor
Ejemplo n.º 2
0
def generateDescriptors(bridge=True, withoutTAP=False, withoutNTOR=False):
    """Create keys, certs, signatures, documents and descriptors for an OR.

    :param bool bridge: If ``True``, generate Bridge descriptors; otherwise,
        generate Relay descriptors.
    :param bool withoutTAP: If ``True``, generate descriptors without
        support for the TAP handshake, e.g. without RSA keys.
    :param bool withoutTAP: If ``True``, generate descriptors without
        support for the ntor handshake, e.g. without Ed25519 keys.
    :returns: A 3-tuple of strings:

      - a ``@type [bridge-]extra-info`` descriptor,
      - a ``@type [bridge-]server-descriptor``, and
      - a ``@type network-status`` document

      for a mock Tor relay/bridge.
    """
    ipv4 = util.randomIPv4()
    ipv6 = util.randomIPv6()
    port = util.randomPort()

    nick = nicknames.generateNickname()
    vers = torversions.getRandomVersion()
    uptime = int(random.randint(1800, 63072000))
    bandwidth = server.makeBandwidthLine()
    timestamp = util.makeTimeStamp(variation=True, period=36)
    protocols = server.makeProtocolsLine(vers)

    if withoutTAP:
        (secretOnionKey, publicOnionKey, onionKeyLine) = (None, None, None)
    else:
        (secretOnionKey, publicOnionKey, onionKeyLine) = crypto.generateOnionKey()
    (secretSigningKey, publicSigningKey, signingKeyLine) = crypto.generateSigningKey()

    secretNTORKey = None
    publicNTORKey = None

    if not withoutNTOR and nacl:
        try:
            secretNTORKey = ntor.createNTORSecretKey()
            publicNTORKey = ntor.getNTORPublicKey(secretNTORKey)
        except ntor.NTORKeyCreationError as error:
            secretNTORKey = None
            publicNTORKey = None
        
    (fingerprintSpacey, fingerprintBinary) = crypto.getFingerprint(publicSigningKey)
    fingerprintSmooshed = crypto.convertToSmooshedFingerprint(fingerprintSpacey)

    extrainfoDoc = extrainfo.generateExtraInfo(nick, fingerprintSmooshed,
                                               timestamp, ipv4, port, bridge=bridge)
    (extrainfoDigestBinary,
     extrainfoDigest,
     extrainfoDigestPKCS1) = crypto.digestDescriptorContent(extrainfoDoc)
    extrainfoDesc = crypto.signDescriptorContent(extrainfoDoc,
                                                 secretSigningKey,
                                                 digest=extrainfoDigestPKCS1)

    serverDoc = server.generateServerDescriptor(nick, fingerprintSpacey,
                                                timestamp, ipv4, ipv6, port,
                                                vers, protocols, uptime,
                                                bandwidth, extrainfoDigest,
                                                onionKeyLine, signingKeyLine,
                                                publicNTORKey, bridge=bridge)
    (serverDigestBinary,
     serverDigest,
     serverDigestPKCS1) = crypto.digestDescriptorContent(serverDoc)

    if bridge:
        serverDoc = b'@purpose bridge\n' + serverDoc

    serverDesc = crypto.signDescriptorContent(serverDoc,
                                              secretSigningKey,
                                              digest=serverDigestPKCS1)

    netstatusDesc = netstatus.generateBridgeNetstatus(nick, fingerprintBinary,
                                                      serverDigestBinary,
                                                      timestamp, ipv4, port,
                                                      ipv6=ipv6,
                                                      bandwidth_line=bandwidth)

    return (extrainfoDesc, serverDesc, netstatusDesc)
Ejemplo n.º 3
0
def generateDescriptors():
    """Create keys, certs, signatures, documents and descriptors for an OR.

    :returns:
        A 3-tuple of strings:
          - a ``@type [bridge-]extra-info`` descriptor,
          - a ``@type [bridge-]server-descriptor``, and
          - a ``@type network-status`` document
       for a mock Tor relay/bridge.
    """
    ipv4 = util.randomIPv4()
    ipv6 = util.randomIPv6()
    port = util.randomPort()

    nick = nicknames.generateNickname()
    vers = torversions.getRandomVersion()
    uptime = int(random.randint(1800, 63072000))
    bandwidth = server.makeBandwidthLine()
    timestamp = util.makeTimeStamp(variation=True, period=36)
    protocols = server.makeProtocolsLine(vers)

    SIDSKey, SIDPCert, (onionkey, signingkey) = crypto.makeOnionKeys()
    idkeyPrivate = tls.getPrivateKey(SIDSKey)
    idkeyDigest = hashlib.sha1(idkeyPrivate).digest()

    idkeyPublic = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_ASN1,
                                                 SIDPCert.get_pubkey())
    idkeyPublic = re.sub(const.OPENSSL_BEGIN_KEY, '', idkeyPublic)
    idkeyPublic = re.sub(const.OPENSSL_END_KEY, '', idkeyPublic)
    idkeyPublic = idkeyPublic.strip()

    identDigest = hashlib.sha1(idkeyPublic).digest()
    fingerprint = hashlib.sha1(idkeyPublic).hexdigest().upper()
    fpr = crypto.convertToSpaceyFingerprint(fingerprint)

    extrainfoDoc = extrainfo.generateExtraInfo(nick, fingerprint,
                                               timestamp, ipv4, port)
    extrainfoDigest = hashlib.sha1(extrainfoDoc).digest()
    extrainfoHexdigest = hashlib.sha1(extrainfoDoc).hexdigest().upper()
    extrainfoSig = crypto.signDescriptorDigest(SIDSKey, extrainfoDigest)
    extrainfoDesc = extrainfoDoc + extrainfoSig

    serverDoc = []
    serverDoc.append("@purpose bridge")
    serverDoc.append("router %s %s %s 0 0" % (nick, ipv4, port))
    serverDoc.append("or-address [%s]:%s" % (ipv6, port))
    serverDoc.append("platform Tor %s on Linux" % vers)
    serverDoc.append("%s\npublished %s" % (protocols, timestamp))
    serverDoc.append("%s" % server.makeFingerprintLine(fingerprint, vers))
    serverDoc.append("uptime %s\n%s" % (uptime, bandwidth))
    serverDoc.append("%s" % server.makeExtraInfoDigestLine(extrainfoHexdigest,
                                                           vers))
    serverDoc.append("%s%s%s" % (onionkey, signingkey,
                                 server.makeHSDirLine(vers)))
    serverDoc.append("contact Somebody <*****@*****.**>")
    if nacl is not None:
        ntorkey = ntor.getNTORPublicKey()
        if ntorkey is not None:
            serverDoc.append("ntor-onion-key %s" % ntorkey)
    serverDoc.append("reject *:*\nrouter-signature\n")

    serverDesc = '\n'.join(serverDoc)
    serverDescDigest = hashlib.sha1(serverDesc).digest()

    netstatusDesc = netstatus.generateNetstatus(nick, identDigest,
                                                serverDescDigest, timestamp,
                                                ipv4, port, ipv6=ipv6,
                                                bandwidth_line=bandwidth)
    serverDesc += crypto.signDescriptorDigest(SIDSKey, serverDescDigest)
    return extrainfoDesc, serverDesc, netstatusDesc