Exemplo n.º 1
0
def bip38_encrypt_privkey(password, privkey, compressFlag=False, **kwargs):
    network = kwargs.get("network", "btc")
    if re.match("^[5KL9c][1-9a-km-zA-LMNP-Z]{50,51}$", privkey):
        compressFlag = "compressed" in get_privkey_format(privkey)
        network = "testnet" if privkey[0] in "9c" else "btc"
        privkey = encode_privkey(decode_privkey(privkey), "hex_compressed" if compressFlag else "hex")
    elif re.match("^[0-9a-f]{64}(01)?$", privkey):
        compressFlag = (len(privkey) == 66 and privkey[-2:] == "01")
    elif len(privkey) in (32, 33):
        privkey = binascii.hexlify(privkey)
    btcprivkey = binascii.unhexlify(privkey)            # 32 byte hex string (no trailing "01")
    
    pubkey = privtopub(privkey)
    addr = privtoaddr(privkey, 111 if network == "testnet" else 0)
    
    pwd = str(unicodedata.normalize("NFC", unicode(password)))
    addrhash = bin_dbl_sha256(addr)[:4]
    scrypthash = pyscrypt.hash(password=pwd, salt=addrhash, N=16384, r=8, p=8, dkLen=64)
    derivedhalf1, derivedhalf2 = scrypthash[:32], scrypthash[32:]
    block1 = strxor(btcprivkey[:16], derivedhalf1[:16])
    block2 = strxor(btcprivkey[16:], derivedhalf1[16:])
    key = derivedhalf2
    encryptedhalf1 = aes_encrypt_bip38(block1, key)
    encryptedhalf2 = aes_encrypt_bip38(block2, key)
    
    prefix = '\x01\x42'             # Do not use EC multiplication
    flagbyte = 0b11000000           # 192
    if compressFlag:
        flagbyte = flagbyte + 0x20  # 224
    flagbyte = encode(flagbyte, 256, 1)
    
    res = prefix + flagbyte + addrhash + encryptedhalf1 + encryptedhalf2
    b58 = bin_to_b58check(res)    # 16PRN7XmtPiu8pHRQGW2DSGrHYLKhb1ny144SnAomjZ9ySY4QcfKenoqXYB
    return b58[1:]                #. 6PRN7XmtPiu8pHRQGW2DSGrHYLKhb1ny144SnAomjZ9ySY4QcfKenoqXYB
Exemplo n.º 2
0
def bip38_encrypt_privkey(password, privkey, compressFlag=False, **kwargs):
    network = kwargs.get("network", "btc")
    if re.match("^[5KL9c][1-9a-km-zA-LMNP-Z]{50,51}$", privkey):
        compressFlag = "compressed" in get_privkey_format(privkey)
        network = "testnet" if privkey[0] in "9c" else "btc"
        privkey = encode_privkey(decode_privkey(privkey), "hex_compressed" if compressFlag else "hex")
    elif re.match("^[0-9a-f]{64}(01)?$", privkey):
        compressFlag = (len(privkey) == 66 and privkey[-2:] == "01")
    elif len(privkey) in (32, 33):
        privkey = binascii.hexlify(privkey)
    btcprivkey = binascii.unhexlify(privkey)            # 32 byte hex string (no trailing "01")
    
    pubkey = privtopub(privkey)
    addr = privtoaddr(privkey, 111 if network == "testnet" else 0)
    
    pwd = str(unicodedata.normalize("NFC", unicode(password)))
    addrhash = bin_dbl_sha256(addr)[:4]
    scrypthash = pyscrypt.hash(password=pwd, salt=addrhash, N=16384, r=8, p=8, dkLen=64)
    derivedhalf1, derivedhalf2 = scrypthash[:32], scrypthash[32:]
    block1 = strxor(btcprivkey[:16], derivedhalf1[:16])
    block2 = strxor(btcprivkey[16:], derivedhalf1[16:])
    key = derivedhalf2
    encryptedhalf1 = aes_encrypt_bip38(block1, key)
    encryptedhalf2 = aes_encrypt_bip38(block2, key)
    
    prefix = '\x01\x42'             # Do not use EC multiplication
    flagbyte = 0b11000000           # 192
    if compressFlag:
        flagbyte = flagbyte + 0x20  # 224
    flagbyte = encode(flagbyte, 256, 1)
    
    res = prefix + flagbyte + addrhash + encryptedhalf1 + encryptedhalf2
    b58 = bin_to_b58check(res)    # 16PRN7XmtPiu8pHRQGW2DSGrHYLKhb1ny144SnAomjZ9ySY4QcfKenoqXYB
    return b58[1:]                #. 6PRN7XmtPiu8pHRQGW2DSGrHYLKhb1ny144SnAomjZ9ySY4QcfKenoqXYB
Exemplo n.º 3
0
  def encrypt(self, message):
      """Produce the PKCS#1 OAEP encryption of a message.
  
      This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in
      section 7.1.1 of RFC3447.
  
      :Parameters:
       message : string
              The message to encrypt, also known as plaintext. It can be of
              variable length, but not longer than the RSA modulus (in bytes)
              minus 2, minus twice the hash output size.
 
      :Return: A string, the ciphertext in which the message is encrypted.
          It is as long as the RSA modulus (in bytes).
      :Raise ValueError:
          If the RSA key length is not sufficiently long to deal with the given
          message.
      """
      # TODO: Verify the key is RSA
  
      randFunc = self._key._randfunc
  
      # See 7.1.1 in RFC3447
      modBits = Crypto.Util.number.size(self._key.n)
      k = ceil_div(modBits,8) # Convert from bits to bytes
      hLen = self._hashObj.digest_size
      mLen = len(message)
  
      # Step 1b
      ps_len = k-mLen-2*hLen-2
      if ps_len<0:
          raise ValueError("Plaintext is too long.")
      # Step 2a
      lHash = self._hashObj.new(self._label).digest()
      # Step 2b
      ps = bchr(0x00)*ps_len
      # Step 2c
      db = lHash + ps + bchr(0x01) + message
      # Step 2d
      ros = randFunc(hLen)
      # Step 2e
      dbMask = self._mgf(ros, k-hLen-1)
      # Step 2f
      maskedDB = strxor(db, dbMask)
      # Step 2g
      seedMask = self._mgf(maskedDB, hLen)
      # Step 2h
      maskedSeed = strxor(ros, seedMask)
      # Step 2i
      em = bchr(0x00) + maskedSeed + maskedDB
      # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP)
      m = self._key.encrypt(em, 0)[0]
      # Complete step 3c (I2OSP)
      c = bchr(0x00)*(k-len(m)) + m
      return c
Exemplo n.º 4
0
    def encrypt(self, message):
        """Produce the PKCS#1 OAEP encryption of a message.
    
        This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in
        section 7.1.1 of RFC3447.
    
        :Parameters:
         message : string
                The message to encrypt, also known as plaintext. It can be of
                variable length, but not longer than the RSA modulus (in bytes)
                minus 2, minus twice the hash output size.
   
        :Return: A string, the ciphertext in which the message is encrypted.
            It is as long as the RSA modulus (in bytes).
        :Raise ValueError:
            If the RSA key length is not sufficiently long to deal with the given
            message.
        """
        # TODO: Verify the key is RSA

        randFunc = self._key._randfunc

        # See 7.1.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes
        hLen = self._hashObj.digest_size
        mLen = len(message)

        # Step 1b
        ps_len = k - mLen - 2 * hLen - 2
        if ps_len < 0:
            raise ValueError("Plaintext is too long.")
        # Step 2a
        lHash = self._hashObj.new(self._label).digest()
        # Step 2b
        ps = bchr(0x00) * ps_len
        # Step 2c
        db = lHash + ps + bchr(0x01) + message
        # Step 2d
        ros = randFunc(hLen)
        # Step 2e
        dbMask = self._mgf(ros, k - hLen - 1)
        # Step 2f
        maskedDB = strxor(db, dbMask)
        # Step 2g
        seedMask = self._mgf(maskedDB, hLen)
        # Step 2h
        maskedSeed = strxor(ros, seedMask)
        # Step 2i
        em = bchr(0x00) + maskedSeed + maskedDB
        # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP)
        m = self._key.encrypt(em, 0)[0]
        # Complete step 3c (I2OSP)
        c = bchr(0x00) * (k - len(m)) + m
        return c
Exemplo n.º 5
0
def EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
    """
    Implement the ``EMSA-PSS-ENCODE`` function, as defined
    in PKCS#1 v2.1 (RFC3447, 9.1.1).

    The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` as input,
    and hash it internally. Here, we expect that the message has already
    been hashed instead.

    :Parameters:
     mhash : hash object
            The hash object that holds the digest of the message being signed.
     emBits : int
            Maximum length of the final encoding, in bits.
     randFunc : callable
            An RNG function that accepts as only parameter an int, and returns
            a string of random bytes, to be used as salt.
     mgf : callable
            A mask generation function that accepts two parameters: a string to
            use as seed, and the lenth of the mask to generate, in bytes.
     sLen : int
            Length of the salt, in bytes.

    :Return: An ``emLen`` byte long string that encodes the hash
            (with ``emLen = \ceil(emBits/8)``).

    :Raise ValueError:
        When digest or salt length are too big.
    """

    emLen = ceil_div(emBits, 8)

    # Bitmask of digits that fill up
    lmask = 0
    for i in xrange(8 * emLen - emBits):
        lmask = lmask >> 1 | 0x80

    # Step 1 and 2 have been already done
    # Step 3
    if emLen < mhash.digest_size + sLen + 2:
        raise ValueError(
            "Digest or salt length are too long for given key size.")
    # Step 4
    salt = b("")
    if randFunc and sLen > 0:
        salt = randFunc(sLen)
    # Step 5 and 6
    h = mhash.new(bchr(0x00) * 8 + mhash.digest() + salt)
    # Step 7 and 8
    db = bchr(0x00) * (emLen - sLen - mhash.digest_size -
                       2) + bchr(0x01) + salt
    # Step 9
    dbMask = mgf(h.digest(), emLen - mhash.digest_size - 1)
    # Step 10
    maskedDB = strxor(db, dbMask)
    # Step 11
    maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:]
    # Step 12
    em = maskedDB + h.digest() + bchr(0xBC)
    return em
Exemplo n.º 6
0
def EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
    """
    Implement the ``EMSA-PSS-ENCODE`` function, as defined
    in PKCS#1 v2.1 (RFC3447, 9.1.1).

    The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` as input,
    and hash it internally. Here, we expect that the message has already
    been hashed instead.

    :Parameters:
     mhash : hash object
            The hash object that holds the digest of the message being signed.
     emBits : int
            Maximum length of the final encoding, in bits.
     randFunc : callable
            An RNG function that accepts as only parameter an int, and returns
            a string of random bytes, to be used as salt.
     mgf : callable
            A mask generation function that accepts two parameters: a string to
            use as seed, and the lenth of the mask to generate, in bytes.
     sLen : int
            Length of the salt, in bytes.

    :Return: An ``emLen`` byte long string that encodes the hash
            (with ``emLen = \ceil(emBits/8)``).

    :Raise ValueError:
        When digest or salt length are too big.
    """

    emLen = ceil_div(emBits,8)

    # Bitmask of digits that fill up
    lmask = 0
    for i in xrange(8*emLen-emBits):
        lmask = lmask>>1 | 0x80

    # Step 1 and 2 have been already done
    # Step 3
    if emLen < mhash.digest_size+sLen+2:
        raise ValueError("Digest or salt length are too long for given key size.")
    # Step 4
    salt = b("")
    if randFunc and sLen>0:
        salt = randFunc(sLen)
    # Step 5 and 6
    h = mhash.new(bchr(0x00)*8 + mhash.digest() + salt)
    # Step 7 and 8
    db = bchr(0x00)*(emLen-sLen-mhash.digest_size-2) + bchr(0x01) + salt
    # Step 9
    dbMask = mgf(h.digest(), emLen-mhash.digest_size-1)
    # Step 10
    maskedDB = strxor(db,dbMask)
    # Step 11
    maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:]
    # Step 12
    em = maskedDB + h.digest() + bchr(0xBC)
    return em
Exemplo n.º 7
0
def EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
    """
    Implement the ``EMSA-PSS-VERIFY`` function, as defined
    in PKCS#1 v2.1 (RFC3447, 9.1.2).

    ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input,
    and hash it internally. Here, we expect that the message has already
    been hashed instead.

    :Parameters:
     mhash : hash object
            The hash object that holds the digest of the message to be verified.
     em : string
            The signature to verify, therefore proving that the sender really signed
            the message that was received.
     emBits : int
            Length of the final encoding (em), in bits.
     mgf : callable
            A mask generation function that accepts two parameters: a string to
            use as seed, and the lenth of the mask to generate, in bytes.
     sLen : int
            Length of the salt, in bytes.

    :Return: 0 if the encoding is consistent, 1 if it is inconsistent.

    :Raise ValueError:
        When digest or salt length are too big.
    """

    emLen = ceil_div(emBits, 8)

    # Bitmask of digits that fill up
    lmask = 0
    for i in xrange(8 * emLen - emBits):
        lmask = lmask >> 1 | 0x80

    # Step 1 and 2 have been already done
    # Step 3
    if emLen < mhash.digest_size + sLen + 2:
        return False
    # Step 4
    if ord(em[-1:]) != 0xBC:
        return False
    # Step 5
    maskedDB = em[:emLen - mhash.digest_size - 1]
    h = em[emLen - mhash.digest_size - 1:-1]
    # Step 6
    if lmask & bord(em[0]):
        return False
    # Step 7
    dbMask = mgf(h, emLen - mhash.digest_size - 1)
    # Step 8
    db = strxor(maskedDB, dbMask)
    # Step 9
    db = bchr(bord(db[0]) & ~lmask) + db[1:]
    # Step 10
    if not db.startswith(
            bchr(0x00) * (emLen - mhash.digest_size - sLen - 2) + bchr(0x01)):
        return False
    # Step 11
    salt = b("")
    if sLen: salt = db[-sLen:]
    # Step 12 and 13
    hp = mhash.new(bchr(0x00) * 8 + mhash.digest() + salt).digest()
    # Step 14
    if h != hp:
        return False
    return True
Exemplo n.º 8
0
  def decrypt(self, ct):
      """Decrypt a PKCS#1 OAEP ciphertext.
  
      This function is named ``RSAES-OAEP-DECRYPT``, and is specified in
      section 7.1.2 of RFC3447.
  
      :Parameters:
       ct : string
              The ciphertext that contains the message to recover.
 
      :Return: A string, the original message.
      :Raise ValueError:
          If the ciphertext length is incorrect, or if the decryption does not
          succeed.
      :Raise TypeError:
          If the RSA key has no private half.
      """
      # TODO: Verify the key is RSA
  
      # See 7.1.2 in RFC3447
      modBits = Crypto.Util.number.size(self._key.n)
      k = ceil_div(modBits,8) # Convert from bits to bytes
      hLen = self._hashObj.digest_size
  
      # Step 1b and 1c
      if len(ct) != k or k<hLen+2:
          raise ValueError("Ciphertext with incorrect length.")
      # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP)
      m = self._key.decrypt(ct)
      # Complete step 2c (I2OSP)
      em = bchr(0x00)*(k-len(m)) + m
      # Step 3a
      lHash = self._hashObj.new(self._label).digest()
      # Step 3b
      y = em[0]
      # y must be 0, but we MUST NOT check it here in order not to
      # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
      maskedSeed = em[1:hLen+1]
      maskedDB = em[hLen+1:]
      # Step 3c
      seedMask = self._mgf(maskedDB, hLen)
      # Step 3d
      seed = strxor(maskedSeed, seedMask)
      # Step 3e
      dbMask = self._mgf(seed, k-hLen-1)
      # Step 3f
      db = strxor(maskedDB, dbMask)
      # Step 3g
      valid = 1
      one = db[hLen:].find(bchr(0x01))
      lHash1 = db[:hLen]
      if lHash1!=lHash:
          valid = 0
      if one<0:
          valid = 0
      if bord(y)!=0:
          valid = 0
      if not valid:
          raise ValueError("Incorrect decryption.")
      # Step 4
      return db[hLen+one+1:]
Exemplo n.º 9
0
def EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
    """
    Implement the ``EMSA-PSS-VERIFY`` function, as defined
    in PKCS#1 v2.1 (RFC3447, 9.1.2).

    ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input,
    and hash it internally. Here, we expect that the message has already
    been hashed instead.

    :Parameters:
     mhash : hash object
            The hash object that holds the digest of the message to be verified.
     em : string
            The signature to verify, therefore proving that the sender really signed
            the message that was received.
     emBits : int
            Length of the final encoding (em), in bits.
     mgf : callable
            A mask generation function that accepts two parameters: a string to
            use as seed, and the lenth of the mask to generate, in bytes.
     sLen : int
            Length of the salt, in bytes.

    :Return: 0 if the encoding is consistent, 1 if it is inconsistent.

    :Raise ValueError:
        When digest or salt length are too big.
    """

    emLen = ceil_div(emBits,8)

    # Bitmask of digits that fill up
    lmask = 0
    for i in xrange(8*emLen-emBits):
        lmask = lmask>>1 | 0x80

    # Step 1 and 2 have been already done
    # Step 3
    if emLen < mhash.digest_size+sLen+2:
        return False
    # Step 4
    if ord(em[-1:])!=0xBC:
        return False
    # Step 5
    maskedDB = em[:emLen-mhash.digest_size-1]
    h = em[emLen-mhash.digest_size-1:-1]
    # Step 6
    if lmask & bord(em[0]):
        return False
    # Step 7
    dbMask = mgf(h, emLen-mhash.digest_size-1)
    # Step 8
    db = strxor(maskedDB, dbMask)
    # Step 9
    db = bchr(bord(db[0]) & ~lmask) + db[1:]
    # Step 10
    if not db.startswith(bchr(0x00)*(emLen-mhash.digest_size-sLen-2) + bchr(0x01)):
        return False
    # Step 11
    salt = b("")
    if sLen: salt = db[-sLen:]
    # Step 12 and 13
    hp = mhash.new(bchr(0x00)*8 + mhash.digest() + salt).digest()
    # Step 14
    if h!=hp:
        return False
    return True
Exemplo n.º 10
0
    def decrypt(self, ct):
        """Decrypt a PKCS#1 OAEP ciphertext.
    
        This function is named ``RSAES-OAEP-DECRYPT``, and is specified in
        section 7.1.2 of RFC3447.
    
        :Parameters:
         ct : string
                The ciphertext that contains the message to recover.
   
        :Return: A string, the original message.
        :Raise ValueError:
            If the ciphertext length is incorrect, or if the decryption does not
            succeed.
        :Raise TypeError:
            If the RSA key has no private half.
        """
        # TODO: Verify the key is RSA

        # See 7.1.2 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes
        hLen = self._hashObj.digest_size

        # Step 1b and 1c
        if len(ct) != k or k < hLen + 2:
            raise ValueError("Ciphertext with incorrect length.")
        # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP)
        m = self._key.decrypt(ct)
        # Complete step 2c (I2OSP)
        em = bchr(0x00) * (k - len(m)) + m
        # Step 3a
        lHash = self._hashObj.new(self._label).digest()
        # Step 3b
        y = em[0]
        # y must be 0, but we MUST NOT check it here in order not to
        # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
        maskedSeed = em[1 : hLen + 1]
        maskedDB = em[hLen + 1 :]
        # Step 3c
        seedMask = self._mgf(maskedDB, hLen)
        # Step 3d
        seed = strxor(maskedSeed, seedMask)
        # Step 3e
        dbMask = self._mgf(seed, k - hLen - 1)
        # Step 3f
        db = strxor(maskedDB, dbMask)
        # Step 3g
        valid = 1
        one = db[hLen:].find(bchr(0x01))
        lHash1 = db[:hLen]
        if lHash1 != lHash:
            valid = 0
        if one < 0:
            valid = 0
        if bord(y) != 0:
            valid = 0
        if not valid:
            raise ValueError("Incorrect decryption.")
        # Step 4
        return db[hLen + one + 1 :]