コード例 #1
0
ファイル: AlertTest.php プロジェクト: tokenly/bitcoin-p2p-php
 public function testNetworkSerializer()
 {
     $network = Bitcoin::getDefaultNetwork();
     $parser = new NetworkMessageSerializer(Bitcoin::getDefaultNetwork());
     $factory = new Factory($network, new Random());
     $version = '1';
     $relayUntil = '9999999';
     $expiration = '9898989';
     $id = '123';
     $cancel = '0';
     $minVer = '0';
     $maxVer = '0';
     $priority = '50';
     $comment = new Buffer('comment');
     $statusBar = new Buffer('statusBar');
     $setCancel = [1, 2];
     $setSubVer = [50, 99];
     $detail = new AlertDetail($version, $relayUntil, $expiration, $id, $cancel, $minVer, $maxVer, $priority, $comment, $statusBar, $setCancel, $setSubVer);
     $adapter = EcAdapterFactory::getPhpEcc(new Math(), EccFactory::getSecgCurves()->generator256k1());
     $sig = new Signature($adapter, '1', '1');
     $alert = $factory->alert($detail, $sig);
     $serialized = $alert->getNetworkMessage()->getBuffer();
     $parsed = $parser->parse($serialized)->getPayload();
     /** @var \BitWasp\Bitcoin\Networking\Messages\Alert $parsed */
     $this->assertEquals($alert->getDetail(), $parsed->getDetail());
     $this->assertEquals($alert->getSignature()->getR(), $parsed->getSignature()->getR());
     $this->assertEquals($alert->getSignature()->getS(), $parsed->getSignature()->getS());
 }
コード例 #2
0
ファイル: Formatter.php プロジェクト: phpecc/x509
 /**
  * @param CertificateInfo $info
  * @return Sequence
  */
 public function getCertInfoAsn(CertificateInfo $info)
 {
     $curve = EccFactory::getSecgCurves()->curve256k1();
     if ($this->extension === null) {
         return new Sequence(new Integer($info->getSerialNo()), new Sequence(SigAlgorithmOidMapper::getSigAlgorithmOid($info->getSigAlgorithm())), $this->subjectSer->toAsn($info->getIssuerInfo()), new Sequence(new UTCTime($info->getValidityStart()->format(CertificateSerializer::UTCTIME_FORMAT)), new UTCTime($info->getValidityEnd()->format(CertificateSerializer::UTCTIME_FORMAT))), $this->subjectSer->toAsn($info->getSubjectInfo()), $this->getSubjectKeyASN($curve, $info->getPublicKey()));
     }
     return new Sequence(new Integer($info->getSerialNo()), new Sequence(SigAlgorithmOidMapper::getSigAlgorithmOid($info->getSigAlgorithm())), $this->subjectSer->toAsn($info->getIssuerInfo()), new Sequence(new UTCTime($info->getValidityStart()->format(CertificateSerializer::UTCTIME_FORMAT)), new UTCTime($info->getValidityEnd()->format(CertificateSerializer::UTCTIME_FORMAT))), $this->subjectSer->toAsn($info->getSubjectInfo()), $this->getSubjectKeyASN($curve, $info->getPublicKey()), $this->extension->apply($info));
 }
コード例 #3
0
ファイル: SecCurveTest.php プロジェクト: sbwdlihao/phpecc
 /**
  *
  * @dataProvider getAdapters
  */
 public function testSecp256r1EquivalenceToNistP192(MathAdapterInterface $adapter)
 {
     $secpFactory = EccFactory::getSecgCurves($adapter);
     $nistFactory = EccFactory::getNistCurves($adapter);
     $signer = new Signer($adapter);
     $secret = $adapter->hexDec('DC51D3866A15BACDE33D96F992FCA99DA7E6EF0934E7097559C27F1614C88A7F');
     $secpKey = $secpFactory->generator256r1()->getPrivateKeyFrom($secret);
     $nistKey = $nistFactory->generator256()->getPrivateKeyFrom($secret);
     $randomK = RandomGeneratorFactory::getRandomGenerator()->generate($secpKey->getPoint()->getOrder());
     $message = RandomGeneratorFactory::getRandomGenerator()->generate($secpKey->getPoint()->getOrder());
     $sigSecp = $signer->sign($secpKey, $message, $randomK);
     $sigNist = $signer->sign($nistKey, $message, $randomK);
     $this->assertEquals($sigNist->getR(), $sigSecp->getR());
     $this->assertEquals($sigNist->getS(), $sigSecp->getS());
 }
コード例 #4
0
ファイル: NumberTheoryTest.php プロジェクト: sbwdlihao/phpecc
 protected function setUp()
 {
     // file containing a json array of {compressed=>'', decompressed=>''} values
     // of compressed and uncompressed ECDSA public keys (testing secp256k1 curve)
     $file_comp = TEST_DATA_DIR . '/compression.json';
     if (!file_exists($file_comp)) {
         $this->fail('Key compression input data not found');
     }
     $file_sqrt = TEST_DATA_DIR . '/square_root_mod_p.json';
     if (!file_exists($file_sqrt)) {
         $this->fail('Square root input data not found');
     }
     $this->generator = EccFactory::getSecgCurves()->generator256k1();
     $this->compression_data = json_decode(file_get_contents($file_comp));
     $this->sqrt_data = json_decode(file_get_contents($file_sqrt));
 }
コード例 #5
0
ファイル: Bitcoin.php プロジェクト: sbwdlihao/bitcoin-php
 /**
  * Load the generator to be used throughout
  */
 public static function getGenerator()
 {
     return EccFactory::getSecgCurves(self::getMath())->generator256k1();
 }
コード例 #6
0
 /**
  * Public Key From MPK
  *
  * This function is used to generate a public key from the supplied
  * $mpk - the master public key, and an $iteration indicating which
  * address in the sequence should be generated.
  *
  * @param    string $mpk
  * @param    int    $iteration
  * @return    string
  */
 public static function public_key_from_mpk($mpk, $iteration, $change = 0, $compressed = false)
 {
     $change = $change == 0 ? '0' : '1';
     $math = EccFactory::getAdapter();
     $gen = EccFactory::getSecgCurves($math)->generator256k1();
     // Generate the curve, and the generator point.
     // Prepare the input values, by converting the MPK to X and Y coordinates
     $x = $math->hexDec(substr($mpk, 0, 64));
     $y = $math->hexDec(substr($mpk, 64, 64));
     // Generate a scalar from the $iteration and $mpk
     $z = $math->hexDec(hash('sha256', hash('sha256', "{$iteration}:{$change}:" . pack('H*', $mpk), true)));
     // Add the Point defined by $x and $y, to the result of EC multiplication of $z by $gen
     $pt = $gen->getCurve()->getPoint($x, $y, $gen->getOrder());
     $pt = $pt->add($gen->mul($z));
     // Generate the uncompressed public key.
     $keystr = '04' . str_pad($math->decHex($pt->getX()), 64, '0', STR_PAD_LEFT) . str_pad($math->decHex($pt->getY()), 64, '0', STR_PAD_LEFT);
     return $compressed == true ? BitcoinLib::compress_public_key($keystr) : $keystr;
 }
コード例 #7
0
ファイル: EcDH.php プロジェクト: rnaga/php-tls
 private function getCurve()
 {
     if (!is_null($this->curve)) {
         return $this->curve;
     }
     switch ($this->type) {
         case self::TYPE_SECP256R1:
             $curve = EccFactory::getSecgCurves()->curve256r1();
             break;
         case self::TYPE_SECP384R1:
             $curve = EccFactory::getSecgCurves()->curve384r1();
             break;
         default:
             return null;
     }
     $this->curve = $curve;
     return $this->curve;
 }
コード例 #8
0
 public function testSignAndIsCanonical()
 {
     $cnt = (getenv('BITCOINLIB_EXTENSIVE_TESTING') ?: 1) * 10;
     $math = EccFactory::getAdapter();
     $G = EccFactory::getSecgCurves()->generator256k1();
     $private = $G->createPrivateKey();
     for ($i = 0; $i < $cnt; $i++) {
         $randomMsgHash = $math->hexDec((string) hash('sha256', 'random' . $i));
         $randomK = $math->hexDec((string) bin2hex(mcrypt_create_iv(32, \MCRYPT_DEV_URANDOM)));
         $signer = new \Mdanter\Ecc\Crypto\Signature\Signer($math);
         $sign = $signer->sign($private, $randomMsgHash, $randomK);
         $this->assertInstanceOf('Mdanter\\Ecc\\Crypto\\Signature\\Signature', $sign);
         $sig = RawTransaction::encode_signature($sign);
         $this->assertTrue(RawTransaction::is_canonical_signature($sig));
     }
 }
コード例 #9
0
ファイル: EcMathTest.php プロジェクト: sbwdlihao/phpecc
 /**
  * @dataProvider getAdapters
  */
 public function testSimpleDeterministicAlgorithm(MathAdapterInterface $math)
 {
     // Set $offset to '0' to confirm it matches with the first output of this program
     $G = EccFactory::getSecgCurves($math)->generator256k1();
     $secret = '2';
     $sharedOffsetDerivedFromMasterPubkey = '2';
     $pubkey = $math->getEcMath($G, $secret)->getPoint();
     // (P+o)%n  -> Only has point
     $pubData = $math->getEcMath($G, $pubkey)->add($sharedOffsetDerivedFromMasterPubkey);
     $this->assertSame('point', $pubData->getType());
     $this->assertSame('103388573995635080359749164254216598308788835304023601477803095234286494993683', $pubData->result()->getX());
     $this->assertSame('37057141145242123013015316630864329550140216928701153669873286428255828810018', $pubData->result()->getY());
     // (k+o)%n  -> Result is int, for the same point.
     $prvData = $math->getEcMath($G, $secret)->add($sharedOffsetDerivedFromMasterPubkey);
     $this->assertSame('int', $prvData->getType());
     $this->assertSame('4', $prvData->result());
     $pub = $prvData->getPoint();
     $this->assertSame('103388573995635080359749164254216598308788835304023601477803095234286494993683', $pub->getX());
     $this->assertSame('37057141145242123013015316630864329550140216928701153669873286428255828810018', $pub->getY());
 }
コード例 #10
0
 /**
  * Sign
  *
  * This function accepts the same parameters as signrawtransaction.
  * $raw_transaction is a hex encoded string for an unsigned/partially
  * signed transaction. $inputs is an array, containing the txid/vout/
  * scriptPubKey/redeemscript. $priv_keys contains WIF keys.
  *
  * The function looks at each TxIn and tries to sign, if the hash160
  * belongs to a key specified in the wallet.
  *
  * @param   array  $wallet
  * @param   string $raw_transaction
  * @param   string $inputs
  * @param   string $magic_byte
  * @param   string $magic_p2sh_byte
  * @return  array
  */
 public static function sign($wallet, $raw_transaction, $inputs, $magic_byte = null, $magic_p2sh_byte = null)
 {
     $math = EccFactory::getAdapter();
     $generator = EccFactory::getSecgCurves($math)->generator256k1();
     $magic_byte = BitcoinLib::magicByte($magic_byte);
     $magic_p2sh_byte = BitcoinLib::magicP2SHByte($magic_p2sh_byte);
     // Generate digests of inputs to sign.
     $message_hash = self::_create_txin_signature_hash($raw_transaction, $inputs);
     $inputs_arr = (array) json_decode($inputs);
     // Generate an association of expected hash160's and related information.
     $decode = self::decode($raw_transaction);
     $req_sigs = 0;
     $sign_count = 0;
     foreach ($decode['vin'] as $vin => $input) {
         $scriptPubKey = self::_decode_scriptPubKey($inputs_arr[$vin]->scriptPubKey);
         $tx_info = self::_get_transaction_type($scriptPubKey, $magic_byte, $magic_p2sh_byte);
         if (isset($wallet[$tx_info['hash160']])) {
             $key_info = $wallet[$tx_info['hash160']];
             $message_hash_dec = $math->hexDec($message_hash[$vin]);
             if ($key_info['type'] == 'scripthash') {
                 $signatures = self::extract_input_signatures_p2sh($input, $message_hash[$vin], $key_info);
                 $sign_count += count($signatures);
                 // Create Signature
                 foreach ($key_info['keys'] as $key) {
                     $key_dec = $math->hexDec($key['private_key']);
                     $k = $math->hexDec((string) bin2hex(mcrypt_create_iv(32, \MCRYPT_DEV_URANDOM)));
                     $signer = new Signer($math);
                     $_private_key = $generator->getPrivateKeyFrom($key_dec);
                     $sign = $signer->sign($_private_key, $message_hash_dec, $k);
                     if ($sign !== false) {
                         $sign_count++;
                         $signatures[$key['public_key']] = self::encode_signature($sign);
                     }
                 }
                 $decode['vin'][$vin]['scriptSig']['hex'] = self::_apply_sig_scripthash_multisig($signatures, $key_info);
                 // Increase required # signature counter.
                 $req_sigs += $key_info['required_signature_count'];
             }
             if ($key_info['type'] == 'pubkeyhash') {
                 $key_dec = $math->hexDec($key_info['private_key']);
                 $signer = new Signer($math);
                 $_private_key = $generator->getPrivateKeyFrom($key_dec);
                 $sign = $signer->sign($_private_key, $message_hash_dec, $math->hexDec((string) bin2hex(mcrypt_create_iv(32, \MCRYPT_DEV_URANDOM))));
                 if ($sign !== false) {
                     $sign_count++;
                     $decode['vin'][$vin]['scriptSig']['hex'] = self::_apply_sig_pubkeyhash(self::encode_signature($sign), $key_info['public_key']);
                 }
                 $req_sigs++;
             }
         } else {
             $req_sigs++;
         }
     }
     $new_raw = self::encode($decode);
     // If the transaction isn't fully signed, return false.
     // If it's fully signed, perform signature verification, return true if valid, or invalid if signatures are incorrect.
     $complete = $req_sigs - $sign_count <= 0 ? self::validate_signed_transaction($new_raw, $inputs, $magic_byte, $magic_p2sh_byte) == true ? 'true' : 'false' : 'false';
     return array('hex' => $new_raw, 'complete' => $complete, 'sign_count' => $sign_count, 'req_sigs' => $req_sigs);
 }
コード例 #11
0
 /**
  * Encode Signature
  *
  * This function accepts a signature object, and information about
  * the txout being spent, and the relevant key for signing, and
  * encodes the signature in DER format.
  *
  * @param    Signature $signature
  * @return    string
  */
 public static function encode_signature(Signature $signature)
 {
     $math = EccFactory::getAdapter();
     $generator = EccFactory::getSecgCurves($math)->generator256k1();
     // if S is > half then we substract from N
     if (self::check_signature_is_high_s($signature)) {
         $n = $generator->getOrder();
         $signature = new Signature($signature->getR(), $math->sub($n, $signature->getS()));
     }
     $rBin = pack("H*", BitcoinLib::hex_encode($signature->getR()));
     $sBin = pack("H*", BitcoinLib::hex_encode($signature->getS()));
     // Pad R and S if their highest bit is flipped, ie,
     // they are negative.
     $rt = $rBin[0] & pack('H*', '80');
     if (ord($rt) == 128) {
         $rBin = pack('H*', '00') . $rBin;
     }
     $st = $sBin[0] & pack('H*', '80');
     if (ord($st) == 128) {
         $sBin = pack('H*', '00') . $sBin;
     }
     $r = bin2hex($rBin);
     $s = bin2hex($sBin);
     // Create the signature.
     $der_sig = '30' . self::_dec_to_bytes(4 + (strlen($r) + strlen($s)) / 2, 1) . '02' . self::pushdata($r) . '02' . self::pushdata($s) . '01';
     return $der_sig;
 }
コード例 #12
0
 /**
  *
  */
 public function setUp()
 {
     $this->math = EccFactory::getAdapter();
     $this->G = EccFactory::getSecgCurves()->generator256k1();
 }
コード例 #13
0
 /**
  * Check Valid HMAC Key
  *
  * This function checks that the generated private keys meet the standard
  * for private keys, as imposed by the secp256k1 curve. The key can't
  * be zero, nor can it >= $n, which is the order of the secp256k1
  * curve. Returning false trigger an error, or cause the program to
  * increase the address number and rerun the CKD function.
  *
  * @param    string $key
  * @return    boolean
  */
 public static function check_valid_hmac_key($key)
 {
     $math = EccFactory::getAdapter();
     $g = EccFactory::getSecgCurves($math)->generator256k1();
     $n = $g->getOrder();
     // initialize the key as a base 16 number.
     $g_l = $math->hexDec($key);
     // compare it to zero
     $_equal_zero = $math->cmp($g_l, 0);
     // compare it to the order of the curve
     $_GE_n = $math->cmp($g_l, $n);
     // Check for invalid data
     if ($_equal_zero == 0 || $_GE_n == 1 || $_GE_n == 0) {
         return false;
     }
     return true;
 }
コード例 #14
0
 /**
  * verify a signed message
  *
  * @param $address
  * @param $signature
  * @param $message
  * @return bool
  * @throws \Exception
  */
 public static function verifyMessage($address, $signature, $message)
 {
     $math = EccFactory::getAdapter();
     $generator = EccFactory::getSecgCurves($math)->generator256k1();
     // extract parameters
     $address = substr(hex2bin(self::base58_decode($address)), 0, -4);
     if (strlen($address) != 21 || $address[0] != hex2bin(self::magicByte())) {
         throw new \InvalidArgumentException('invalid Bitcoin address');
     }
     $signature = base64_decode($signature, true);
     if ($signature === false) {
         throw new \InvalidArgumentException('invalid base64 signature');
     }
     if (strlen($signature) != 65) {
         throw new \InvalidArgumentException('invalid signature length');
     }
     $recoveryFlags = ord($signature[0]) - 27;
     if ($recoveryFlags < 0 || $recoveryFlags > 7) {
         throw new \InvalidArgumentException('invalid signature type');
     }
     $isCompressed = ($recoveryFlags & 4) != 0;
     // message is <varInt><prefix><varInt><message>
     $messageHash = "Bitcoin Signed Message:\n" . hex2bin(RawTransaction::_encode_vint(strlen($message))) . $message;
     $messageHash = hash('sha256', hash('sha256', $messageHash, true), true);
     try {
         $pubkey = self::recoverPubKey($math->hexDec(bin2hex(substr($signature, 1, 32))), $math->hexDec(bin2hex(substr($signature, 33, 32))), $math->hexDec(bin2hex($messageHash)), $recoveryFlags, $generator);
     } catch (\Exception $e) {
         throw new \Exception("unable to recover key", 0, $e);
     }
     if ($pubkey === false) {
         throw new \Exception('unable to recover key');
     }
     $point = $pubkey->getPoint();
     // see that the key we recovered is for the address given
     if (!$isCompressed) {
         $pubBinStr = "" . str_pad(hex2bin(self::padHex($math->decHex($point->getX()))), 32, "", STR_PAD_LEFT) . str_pad(hex2bin(self::padHex($math->decHex($point->getY()))), 32, "", STR_PAD_LEFT);
     } else {
         $pubBinStr = ($math->mod($point->getY(), 2) == 0 ? "" : "") . str_pad(hex2bin(self::padHex($math->decHex($point->getX()))), 32, "", STR_PAD_LEFT);
     }
     $derivedAddress = hex2bin(self::magicByte()) . hash('ripemd160', hash('sha256', $pubBinStr, true), true);
     return $address === $derivedAddress;
 }