Example #1
0
 def verify(self, commitment, index_range):
     """For an object created without a private key,
     check that the opened commitment verifies for at least
     one NUMS point as defined by the range in index_range
     """
     if not all([self.P, self.P2, self.s, self.e]):
         raise PoDLEError("Verify called without sufficient data")
     if not self.get_commitment() == commitment:
         return False
     for J in [getNUMS(i) for i in index_range]:
         sig_priv = podle_PrivateKey(self.s)
         sG = sig_priv.pubkey
         sJ = multiply(self.s, J.serialize(), False)
         e_int = decode(self.e, 256)
         minus_e = encode(-e_int % N, 256, minlen=32)
         minus_e_P = multiply(minus_e, self.P.serialize(), False)
         minus_e_P2 = multiply(minus_e, self.P2.serialize(), False)
         KGser = add_pubkeys([sG.serialize(), minus_e_P], False)
         KJser = add_pubkeys([sJ, minus_e_P2], False)
         #check 2: e =?= H(K_G || K_J || P || P2)
         e_check = hashlib.sha256(KGser + KJser + self.P.serialize() +
                                  self.P2.serialize()).digest()
         if e_check == self.e:
             return True
     #commitment fails for any NUMS in the provided range
     return False
Example #2
0
    def generate_podle(self, index=0, k=None):
        """Given a raw private key, in hex format,
        construct a commitment sha256(P2), which is
        the hash of the value x*J, where x is the private
        key as a raw scalar, and J is a NUMS alternative
        basepoint on the Elliptic Curve; we use J(i) where i
        is an index, so as to be able to create multiple
        commitments against the same privkey. The procedure
        for generating the J(i) value is shown in getNUMS().
        Also construct a signature (s,e) of Schnorr type,
        which will serve as a zero knowledge proof that the
        private key of P2 is the same as the private key of P (=x*G).
        Signature is constructed as:
        s = k + x*e
        where k is a standard 32 byte nonce and:
        e = sha256(k*G || k*J || P || P2)

        Possibly Joinmarket specific comment:
        Users *should* generate with lower indices first,
        since verifiers will give preference to lower indices
        (each verifier may have their own policy about how high
        an index to allow, which really means how many reuses of utxos
        to allow in Joinmarket).

        Returns a commitment of form H(P2) which, note, will depend
        on the index choice. Repeated calls will reset the commitment
        and the associated signature data that can be used to open
        the commitment.
        """
        #TODO nonce could be rfc6979?
        if not k:
            k = os.urandom(32)
        J = getNUMS(index)
        KG = podle_PrivateKey(k).pubkey
        KJ = multiply(k, J.serialize(), False, return_serialized=False)
        self.P2 = getP2(self.priv, J)
        self.get_commitment()
        self.e = hashlib.sha256(''.join(
            [x.serialize() for x in [KG, KJ, self.P, self.P2]])).digest()
        k_int = decode(k, 256)
        priv_int = decode(self.priv.private_key, 256)
        e_int = decode(self.e, 256)
        sig_int = (k_int + priv_int * e_int) % N
        self.s = encode(sig_int, 256, minlen=32)
        return self.reveal()
Example #3
0
 def __init__(self,
              u=None,
              priv=None,
              P=None,
              P2=None,
              s=None,
              e=None,
              used=False):
     #This class allows storing of utxo in format "txid:n" only for
     #convenience of storage/access; it doesn't check or use the data.
     #Arguments must be provided in hex.
     self.u = u
     if not priv:
         if P:
             #Construct a pubkey from raw hex
             self.P = podle_PublicKey(binascii.unhexlify(P))
         else:
             self.P = None
     else:
         if P:
             raise PoDLEError("Pubkey should not be provided with privkey")
         #any other formatting abnormality will just throw in PrivateKey
         if len(priv) == 66 and priv[-2:] == '01':
             priv = priv[:-2]
         self.priv = podle_PrivateKey(binascii.unhexlify(priv))
         self.P = self.priv.pubkey
     if P2:
         self.P2 = podle_PublicKey(binascii.unhexlify(P2))
     else:
         self.P2 = None
     #These sig values should be passed in hex.
     self.s = None
     self.e = None
     if s:
         self.s = binascii.unhexlify(s)
     if e:
         self.e = binascii.unhexlify(e)
     #Optionally maintain usage state (boolean)
     self.used = used
     #the H(P2) value
     self.commitment = None