Skip to content

Commit

Permalink
added examples and added setPrivateKeyWithWif method
Browse files Browse the repository at this point in the history
  • Loading branch information
rgex committed Apr 16, 2017
1 parent 068277f commit 0d83cf2
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 43 deletions.
17 changes: 17 additions & 0 deletions Examples/generateAddress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

require_once '../src/BitcoinPHP/BitcoinECDSA/BitcoinECDSA.php';

use BitcoinPHP\BitcoinECDSA\BitcoinECDSA;

$bitcoinECDSA = new BitcoinECDSA();
$bitcoinECDSA->generateRandomPrivateKey(); //generate new random private key
$address = $bitcoinECDSA->getAddress(); //compressed Bitcoin address
echo "Address: " . $address . PHP_EOL;

//Validate an address (Verify the checksum)
if($bitcoinECDSA->validateAddress($address)) {
echo "The address is valid" . PHP_EOL;
} else {
echo "The address is invalid" . PHP_EOL;
}
36 changes: 36 additions & 0 deletions Examples/signMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

require_once '../src/BitcoinPHP/BitcoinECDSA/BitcoinECDSA.php';

use BitcoinPHP\BitcoinECDSA\BitcoinECDSA;

$bitcoinECDSA = new BitcoinECDSA();
$bitcoinECDSA->generateRandomPrivateKey(); //generate new random private key

$message = "Test message";
$signedMessage = $bitcoinECDSA->signMessage($message);

echo "signed message:" . PHP_EOL;
echo $signedMessage . PHP_EOL;

/**
* Will print something like this:
-----BEGIN BITCOIN SIGNED MESSAGE-----
Test message
-----BEGIN SIGNATURE-----
1L56ndSQ1LfrAB2xyo3ZN7egiW4nSs8KWS
HxTqM+b3xj2Qkjhhl+EoUpYsDUz+uTdz6RCY7Z4mV62yOXJ3XCAfkiHV+HGzox7Ba/OC6bC0y6zBX0GhB7UdEM0=
-----END BITCOIN SIGNED MESSAGE-----
*/


// If you only want the signature you can do this
$signature = $bitcoinECDSA->signMessage($message, true);

echo "signature:" . PHP_EOL;
echo $signature . PHP_EOL;
/**
* Will print something like this:
HxTqM+b3xj2Qkjhhl+EoUpYsDUz+uTdz6RCY7Z4mV62yOXJ3XCAfkiHV+HGzox7Ba/OC6bC0y6zBX0GhB7UdEM0=
*/
32 changes: 32 additions & 0 deletions Examples/verifyMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

require_once '../src/BitcoinPHP/BitcoinECDSA/BitcoinECDSA.php';

use BitcoinPHP\BitcoinECDSA\BitcoinECDSA;

$bitcoinECDSA = new BitcoinECDSA();

//To verify a message like this one
$rawMessage = "-----BEGIN BITCOIN SIGNED MESSAGE-----
Test message
-----BEGIN SIGNATURE-----
1L56ndSQ1LfrAB2xyo3ZN7egiW4nSs8KWS
HxTqM+b3xj2Qkjhhl+EoUpYsDUz+uTdz6RCY7Z4mV62yOXJ3XCAfkiHV+HGzox7Ba/OC6bC0y6zBX0GhB7UdEM0=
-----END BITCOIN SIGNED MESSAGE-----";

if($bitcoinECDSA->checkSignatureForRawMessage($rawMessage)) {
echo "Message verified" . PHP_EOL;
} else {
echo "Couldn't verify message" . PHP_EOL;
}

// alternatively
$signature = "HxTqM+b3xj2Qkjhhl+EoUpYsDUz+uTdz6RCY7Z4mV62yOXJ3XCAfkiHV+HGzox7Ba/OC6bC0y6zBX0GhB7UdEM0=";
$address = "1L56ndSQ1LfrAB2xyo3ZN7egiW4nSs8KWS";
$message = "Test message";

if($bitcoinECDSA->checkSignatureForMessage($address, $signature, $message)) {
echo "Message verified" . PHP_EOL;
} else {
echo "Couldn't verify message" . PHP_EOL;
}
25 changes: 25 additions & 0 deletions Examples/wif.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

require_once '../src/BitcoinPHP/BitcoinECDSA/BitcoinECDSA.php';

use BitcoinPHP\BitcoinECDSA\BitcoinECDSA;

$bitcoinECDSA = new BitcoinECDSA();
$bitcoinECDSA->generateRandomPrivateKey(); //generate new random private key

$wif = $bitcoinECDSA->getWif();
$address = $bitcoinECDSA->getAddress();
echo "Address : " . $address . PHP_EOL;
echo "WIF : " . $wif . PHP_EOL;

unset($bitcoinECDSA); //destroy instance

//import wif
$bitcoinECDSA = new BitcoinECDSA();
if($bitcoinECDSA->validateWifKey($wif)) {
$bitcoinECDSA->setPrivateKeyWithWif($wif);
$address = $bitcoinECDSA->getAddress();
echo "imported address : " . $address . PHP_EOL;
} else {
echo "invalid WIF key" . PHP_EOL;
}
102 changes: 59 additions & 43 deletions src/BitcoinPHP/BitcoinECDSA/BitcoinECDSA.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,26 +243,6 @@ public function base58_decode($encodedData, $littleEndian = true)
return $res;
}

/***
* returns the private key under the Wallet Import Format
*
* @return string (base58)
* @throws \Exception
*/
public function getWif()
{
if(!isset($this->k))
{
throw new \Exception('No Private Key was defined');
}

$k = $this->k;
$secretKey = '80' . $k;
$secretKey .= substr($this->hash256(hex2bin($secretKey)), 0, 8);

return $this->base58_encode($secretKey);
}

/***
* Computes the result of a point addition and returns the resulting point as an Array.
*
Expand Down Expand Up @@ -602,9 +582,9 @@ public function getDerPubKeyWithPubKeyPoints($pubKey, $compressed = true)
else
{
if(gmp_strval(gmp_mod(gmp_init($pubKey['y'], 16), gmp_init(2, 10))) === '0')
$pubKey = '02' . $pubKey['x']; //if $pubKey['y'] is even
$pubKey = '02' . $pubKey['x']; //if $pubKey['y'] is even
else
$pubKey = '03' . $pubKey['x']; //if $pubKey['y'] is odd
$pubKey = '03' . $pubKey['x']; //if $pubKey['y'] is odd

return $pubKey;
}
Expand Down Expand Up @@ -658,13 +638,13 @@ public function getPubKeyPoints()
throw new \Exception('No Private Key was defined');
}

$pubKey = $this->mulPoint(
$pubKey = $this->mulPoint(
$k,
['x' => $G['x'], 'y' => $G['y']]
);

$pubKey['x'] = gmp_strval($pubKey['x'], 16);
$pubKey['y'] = gmp_strval($pubKey['y'], 16);
$pubKey['x'] = gmp_strval($pubKey['x'], 16);
$pubKey['y'] = gmp_strval($pubKey['y'], 16);

while(strlen($pubKey['x']) < 64)
{
Expand Down Expand Up @@ -708,9 +688,9 @@ public function getPubKey(array $pubKeyPts = [])
$pubKeyPts = $this->getPubKeyPoints();

if(gmp_strval(gmp_mod(gmp_init($pubKeyPts['y'], 16), gmp_init(2, 10))) === '0')
$compressedPubKey = '02' . $pubKeyPts['x']; //if $pubKey['y'] is even
$compressedPubKey = '02' . $pubKeyPts['x']; //if $pubKey['y'] is even
else
$compressedPubKey = '03' . $pubKeyPts['x']; //if $pubKey['y'] is odd
$compressedPubKey = '03' . $pubKeyPts['x']; //if $pubKey['y'] is odd

return $compressedPubKey;
}
Expand All @@ -729,27 +709,27 @@ public function getUncompressedAddress($compressed = false, $derPubKey = null)
if($derPubKey !== null)
{
if($compressed === true) {
$address = $this->getPubKey($this->getPubKeyPointsWithDerPubKey($derPubKey));
$address = $this->getPubKey($this->getPubKeyPointsWithDerPubKey($derPubKey));
}
else {
$address = $this->getUncompressedPubKey($this->getPubKeyPointsWithDerPubKey($derPubKey));
$address = $this->getUncompressedPubKey($this->getPubKeyPointsWithDerPubKey($derPubKey));
}
}
else
{
if($compressed === true) {
$address = $this->getPubKey();
$address = $this->getPubKey();
}
else {
$address = $this->getUncompressedPubKey();
$address = $this->getUncompressedPubKey();
}
}

$address = $this->getNetworkPrefix() . $this->hash160(hex2bin($address));
$address = $this->getNetworkPrefix() . $this->hash160(hex2bin($address));

//checksum
$address = $address.substr($this->hash256(hex2bin($address)), 0, 8);
$address = $this->base58_encode($address);
$address = $address.substr($this->hash256(hex2bin($address)), 0, 8);
$address = $this->base58_encode($address);

if($this->validateAddress($address))
return $address;
Expand Down Expand Up @@ -827,6 +807,26 @@ public function validateAddress($address)
return false;
}

/***
* returns the private key under the Wallet Import Format
*
* @return string (base58)
* @throws \Exception
*/
public function getWif()
{
if(!isset($this->k))
{
throw new \Exception('No Private Key was defined');
}

$k = $this->k;
$secretKey = '80' . $k;
$secretKey .= substr($this->hash256(hex2bin($secretKey)), 0, 8);

return $this->base58_encode($secretKey);
}

/***
* Tests if the Wif key (Wallet Import Format) is valid or not.
*
Expand All @@ -835,15 +835,29 @@ public function validateAddress($address)
*/
public function validateWifKey($wif)
{
$key = $this->base58_decode($wif, false);
$length = strlen($key);
$key = $this->base58_decode($wif, true);
$length = strlen($key);
$checksum = $this->hash256(hex2bin(substr($key, 0, $length - 8)));
if(substr($checksum, 0, 8) === substr($key, $length - 8, 8))
return true;
else
return false;
}

/**
* @param string $wif (base58)
* @return bool
*/
public function setPrivateKeyWithWif($wif)
{
if(!$this->validateWifKey($wif)) {
throw new \Exception('Invalid WIF');
}

$key = $this->base58_decode($wif, true);
$this->setPrivateKey(substr($key, 1, strlen($key) - 9));
}

/***
* Sign a hash with the private key that was set and returns signatures as an array (R,S)
*
Expand Down Expand Up @@ -945,15 +959,16 @@ public function signHash($hash, $nonce = null)
* Satoshi client's standard message signature implementation.
*
* @param string $message
* @param bool $onlySignature
* @param bool $compressed
* @param null $nonce
* @return string
* @throws \Exception
*/
public function signMessage($message, $compressed = true, $nonce = null)
public function signMessage($message, $onlySignature = false ,$compressed = true, $nonce = null)
{

$hash = $this->hash256("\x18Bitcoin Signed Message:\n" . $this->numToVarIntString(strlen($message)). $message);
$hash = $this->hash256("\x18Bitcoin Signed Message:\n" . $this->numToVarIntString(strlen($message)). $message);
$points = $this->getSignatureHashPoints(
$hash,
$nonce
Expand Down Expand Up @@ -985,12 +1000,8 @@ public function signMessage($message, $compressed = true, $nonce = null)
$flag += $i;

$pubKeyPts = $this->getPubKeyPoints();
//echo "\nReal pubKey : \n";
//print_r($pubKeyPts);

$recoveredPubKey = $this->getPubKeyWithRS($flag, $R, $S, $hash);
//echo "\nRecovered PubKey : \n";
//print_r($recoveredPubKey);

if($this->getDerPubKeyWithPubKeyPoints($pubKeyPts, $compressed) === $recoveredPubKey)
{
Expand All @@ -1004,8 +1015,13 @@ public function signMessage($message, $compressed = true, $nonce = null)
throw new \Exception('Unable to get a valid signature flag.');
}

$signature = base64_encode(hex2bin(dechex($finalFlag) . $R . $S));

if($onlySignature) {
return $signature;
}

$res .= base64_encode(hex2bin(dechex($finalFlag) . $R . $S));
$res .= $signature;
$res .= "\n-----END BITCOIN SIGNED MESSAGE-----";

return $res;
Expand Down

0 comments on commit 0d83cf2

Please sign in to comment.