Cryptography
Various cryptographic global functions. Crypto-oriented extension functions for Cell
, Builder
, and Slice
types are listed on their reference page: Cells, Builders and Slices.
checkSignature
fun checkSignature(hash: Int, signature: Slice, publicKey: Int): Bool;
Checks the Ed25519 signature
of the 256-bit unsigned Int
hash
using a publicKey
, represented by a 256-bit unsigned Int
. The signature must contain at least 512 bits of data, but only the first 512 bits are used.
Returns true
if the signature is valid, false
otherwise.
Usage example:
message ExtMsg { signature: Slice; data: Cell;}
contract Showcase { // Persistent state variables pub: Int as uint256; // public key as a 256-bit unsigned Int
// Constructor function init(), where all variables are initialized init(pub: Int) { self.pub = pub; // storing the public key upon contract initialization }
// External message receiver, which accepts message ExtMsg external(msg: ExtMsg) { let hash: Int = beginCell().storeRef(msg.data).endCell().hash(); let check: Bool = checkSignature(hash, msg.signature, self.pub); // ---- ------------- -------- // ↑ ↑ ↑ // | | publicKey stored in our contract // | signature obtained from the received message // hash calculated using the data from the received message // ... follow-up logic ... }}
checkDataSignature
fun checkDataSignature(data: Slice, signature: Slice, publicKey: Int): Bool;
Checks the Ed25519 signature
of the data
using a publicKey
, similar to checkSignature()
. If the bit length of data
is not divisible by 8, this function throws an error with exit code 9: Cell underflow
. Verification itself is done indirectly on a SHA-256 hash of the data
.
Returns true
if the signature is valid, false
otherwise.
Usage example:
let data: Slice = someData;let signature: Slice = someSignature;let publicKey: Int = 42;
let check: Bool = checkDataSignature(data, signature, publicKey);
SignedBundle
Available since Tact 1.6.6struct SignedBundle { /// A 512-bit Ed25519 signature of the `signedData`. signature: Slice as bytes64;
/// The remaining non-serialized data of the enclosing struct or message struct, /// which was used to obtain the 512-bit Ed25519 `signature`. signedData: Slice as remaining;}
A struct that contains a 512-bit Ed25519 signature and the data it signs.
See the usage example for the SignedBundle.verifySignature()
function.
SignedBundle.verifySignature
Available since Tact 1.6.6extends fun verifySignature(self: SignedBundle, publicKey: Int): Bool;
Extension function for the SignedBundle
struct.
Checks whether self.signedData
was signed by the 512-bit Ed25519 signature self.signature
, using the given publicKey
. Returns true
if the signature is valid, false
otherwise.
Usage example:
contract Example(publicKey: Int as uint256) { external(msg: MessageWithSignedData) { // Checks that the signature of the SignedBundle from the incoming external // message wasn't forged and made by the owner of this self.publicKey with // its respective private key managed elsewhere. throwUnless(35, msg.bundle.verifySignature(self.publicKey));
// ...rest of the checks and code... }}
message MessageWithSignedData { // The `bundle.signature` contains the 512-bit Ed25519 signature // of the remaining data fields of this message struct, // while `bundle.signedData` references those data fields. // In this case, the fields are `walletId` and `seqno`. bundle: SignedBundle;
// These fields are common to external messages to user wallets. walletId: Int as int32; seqno: Int as uint32;}
sha256
Gas-expensivefun sha256(data: Slice): Int;fun sha256(data: String): Int;
Computes and returns the SHA-256 hash as a -bit unsigned Int
from the passed Slice
or String
data
, which should have a number of bits divisible by .
In case data
is a Slice
, it must have no more than a single reference per cell, because only the first reference of each nested cell will be taken into account.
This function tries to resolve constant string values at compile-time whenever possible.
Attempts to specify a Slice
or String
with a number of bits not divisible by throw an exception with exit code 9: Cell underflow
.
Usage examples:
sha256(beginCell().asSlice());sha256("Hello, world!"); // will be resolved at compile-timesha256(someVariableElsewhere); // will try to resolve at compile-time, // and fall back to run-time evaluation
keccak256
Gas-expensive Available since Tact 1.6.6fun keccak256(data: Slice): Int;
Computes and returns the Ethereum-compatible Keccak-256 hash as a 256-bit unsigned Int
from the passed Slice
data
.
The data
slice should have a number of bits divisible by 8 and no more than a single reference per cell, because only the first reference of each nested cell will be taken into account.
Attempts to specify a Slice
with a number of bits not divisible by 8 throw an exception with exit code 9: Cell underflow
.
Usage examples:
contract Examples() { receive(rawMsg: Slice) { // Hash incoming message body Slice let hash: Int = keccak256(rawMsg);
// Process data that spans multiple cells let b: Builder = beginCell() .storeUint(123456789, 32) .storeRef(beginCell().storeString("Extra data in a ref").endCell()); let largeDataHash: Int = keccak256(b.asSlice());
// Match Ethereum's hash format let ethAddress: String = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; let ethAddressHash: Int = keccak256(ethAddress.asSlice()); }}