_Signing and addresses
composer require legalthings/lto-api
$seedText = "manage manual recall harvest series desert melt police rose hollow moral pledge kitten position add";
$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$account = $factory->seed($seedText);
$secretKey = 'wJ4WH8dD88fSkNdFQRjaAhjFUZzZhV5yiDLDwNUnp6bYwRXrvWV8MJhQ9HL9uqMDG1n7XpTGZx7PafqaayQV8Rp';
$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$account = $factory->create($secretKey);
$accountInfo = [
'address' => '3PLSsSDUn3kZdGe8qWEDak9y8oAjLVecXV1',
'sign' => [
'secretkey' => 'wJ4WH8dD88fSkNdFQRjaAhjFUZzZhV5yiDLDwNUnp6bYwRXrvWV8MJhQ9HL9uqMDG1n7XpTGZx7PafqaayQV8Rp',
'publickey' => 'FkU1XyfrCftc4pQKXCrrDyRLSnifX1SMvmx1CYiiyB3Y'
],
'encrypt' => [
'secretkey' => 'BnjFJJarge15FiqcxrB7Mzt68nseBXXR4LQ54qFBsWJN',
'publickey' => 'BVv1ZuE3gKFa6krwWJQwEmrLYUESuUabNCXgYTmCoBt6'
]
];
$factory = new LTO\AccountFactory('T'); // 'T' for testnet, 'L' for mainnet
$account = $factory->create($accountInfo);
Properties that are specified will be verified. Properties that are omitted will be generated where possible.
$signature = $account->sign('hello world'); // Base58 encoded signature
if (!$account->verify($signature, 'hello world')) {
throw new RuntimeException('invalid signature');
}
$message = 'hello world';
$recipientPublicKey = "HBqhfdFASRQ5eBBpu2y6c6KKi1az6bMx8v1JxX4iW1Q8"; // base58 encoded X25519 public key
$recipient = $factory->createPublic(null, $recipientPublicKey);
$cyphertext = $account->encryptFor($recipient, $message); // Raw binary, not encoded
You can use $account->encryptFor($account, $message);
to encrypt a message for yourself.
$senderPublicKey = "HBqhfdFASRQ5eBBpu2y6c6KKi1az6bMx8v1JxX4iW1Q8"; // base58 encoded X25519 public key
$sender = $factory->createPublic(null, $senderPublicKey);
$message = $account->decryptFrom($sender, $cyphertext);
You can use $account->decryptFrom($account, $message);
to decrypt a message from yourself.
$chain = $account->createEventChain(); // Creates an empty event chain with a valid id and last hash
Note: You need to add an identity as first event on the chain. This is not done automatically.
$body = [
"$schema": "http://specs.livecontracts.io/01-draft/12-comment/schema.json#",
"identity": {
"$schema": "http://specs.livecontracts.io/01-draft/02-identity/schema.json#",
"id": "1bb5a451-d496-42b9-97c3-e57404d2984f"
},
"content_media_type": "text/plain",
"content": "Hello world!"
];
$chainId = "JEKNVnkbo3jqSHT8tfiAKK4tQTFK7jbx8t18wEEnygya";
$chainLastHash" = "3yMApqCuCjXDWPrbjfR5mjCPTHqFG8Pux1TxQrEM35jj";
$chain = new LTO\EventChain($chainId, $chainLastHash);
$chain->add(new Event($body))->signWith($account);
You need the chain id and the hash of the last event to use an existing chain.
Signing HTTP Messages is described IETF draft draft-cavage-http-signatures-09.
HTTP Signature Authentication is applied to PSR-7 requests.
$request = new GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org/get');
$httpSignature = new LTO\HTTPSignature($request, ['(request-target)', 'date']);
$signedRequest = $httpSignature->signWith($account);
$client = new GuzzleHttp\Client();
$client->send($request);
Verifying a signed HTTP request requires using a PSR-7 compliant framework. Assume that Response
is an implementation
of Psr\Http\Message\ResponseInterface
.
function handleRequest(Psr\Http\Message\RequestInterface $request)
{
$accountFactory = new LTO\AccountFactory('T');
$requiredHeaders = $this->getMethod() === 'POST'
? ['(request-target)', 'date', 'content-type', 'content-length', 'digest']
: ['(request-target)', 'date'];
try {
$httpSignature = new LTO\HTTPSignature($this->getRequest(), $requiredHeaders);
$httpSignature->useAccountFactory($accountFactory)->verify();
$account = $httpSignature->getAccount();
// The account can be used for access control
$response = (new Response())->withStatusCode(200);
} catch (LTO\HTTPSignatureException $e) {
$wwwAuthHeader = sprintf('Signature algorithm="ed25519-sha256",headers="%s"', join(' ', $requiredHeaders));
$response = (new Response())->withStatusCode(401)->withHeader("WWW-Authenticate", $wwwAuthHeader);
}
return $response;
}