Continuing with Sapphire tutorial, we learnt in part 1 about Oasis architecture and confidential transaction, and in part 2 about signed view calls, frontend, and precompiles. #5: What to do next? This section will touch upon encryption & decryption, signing & verification, autonomous contracts, Oasis Privacy Layer (OPL), running nodes, etc. Encryption & Decryption We know now that end-to-end encryption is possible between user and smart contract where storage is on the public ledger in encrypted form. But, it is also possible to use X25519 key pairs inside a smart contract and derive shared secret on-chain. ECDH states that two people with their own key pairs, when they have each others public keys they can both derive the point, and nobody else can, unless one of the secrets gets leaked. Use cases Encrypted emitted events, stateless view calls Encrypted coupons, proxies, authentication, compliance Encryption (TypeScript) import * as sapphire from '@oasisprotocol/sapphire-paratime'const e2ePubKey = await e2e.getPublicKey();const box = sapphire.cipher.X25519DeoxysII.ephemeral(e2ePubKey);let {nonce, cipherText} = await box.encrypt(plaintextBytes);const nonceBytes32Hex = ethers.utils.hexlify(nonce) +"0000000000000000000000000000000000"; Decryption (Solidity) import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";contract E2EProxy {Sapphire.Curve25519PublicKey internal immutable publicKey;Sapphire.Curve25519SecretKey internal immutable privateKey;constructor (bytes memory extraEntropy) {(publicKey, privateKey) = Sapphire.generateCurve25519KeyPair(extraEntropy);}function getPublicKey() external view returns (bytes32) {return Sapphire.Curve25519PublicKey.unwrap(publicKey);}} import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";contract E2EProxy {function decrypt(bytes32 peerPublicKey, bytes32 nonce, bytes memory data)external{bytes32 sk = Sapphire.deriveSymmetricKey(Sapphire.Curve25519PublicKey.wrap(peerPublicKey),privateKey);bytes memory plaintext = Sapphire.decrypt(sk, nonce, data, "");}} Signing & Verification Contracts can generate key-pairs (Ed25519, X25519, Bitcoin & NIST) Signing with EcDSA and EdDSA There are various utilities for this. You can generate Ethereum addresses and sign transactions on-chain. You can verify WebAuthN / TouchID, using Ed25519 & EdDSA You can broadcast cross-chain without bridge dependency Signing (Solidity) import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";contract SigningExample {function sign(bytes32 hashed_message)external returns (bytes){Sapphire.SigningAlg alg =Sapphire.SigningAlg.Secp256k1PrehashedKeccak256;bytes memory pk;bytes memory sk;bytes memory digest = abi.encodePacked(hashed_message);Bytes memory entropy = Sapphire.randomBytes(32, "");(pk, sk) = Sapphire.generateSigningKeyPair(alg, entropy);return Sapphire.sign(alg, sk, digest, "");}} Verification (Solidity) import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";contract VerifyExample {function verify(bytes32 hashed_message, bytes memory signature)external returns (bool){Sapphire.SigningAlg alg =Sapphire.SigningAlg.Secp256k1PrehashedKeccak256;bytes memory digest = abi.encodePacked(hashed_message);return Sapphire.verify(alg, pk, digest, "", signature);}} On-chain Single Sign-On Viewing Keys — submitting an access token to view your data. Permits — providing access to specific functions (read/write). Daily Login with EIP-712: a. it is similar to permits but is application-specific b. it lets you sign a transaction once on a daily or weekly basis Explore this more with Oasis docs on Sapphire. Autonomous Contracts Using the key generation precompiles, Sapphire can generate Ethereum compatible accounts to pay their own gas — either on Sapphire or on other EVM compatible chains. Ethereum compatible key-generation & signing is included in the@oasisprotocol/sapphire-contracts package: EthereumUtils.sol — a, s = EthereumUtils.generateKeypair() EIP155Signer.sol — struct EIP155Signer.EthTx- EIP155Signer.sign(address,secret,tx) Ethereum Keypair Generation and Signing (Solidity) import '@oasisprotocol/sapphire-contracts/contracts/EthereumUtils.sol';contract KeypairExample {address pubkey;bytes32 secret;constructor () {(pubkey, secret) = EthereumUtils.generateKeypair();}function sign(bytes memory data)external view returns (SignatureRSV memory rsv){bytes32 digest = keccak256(data);rsv = EthereumUtils.sign(pubkey, secret, digest);}} Transaction Signing (Solidity) function signTx(uint64 nonce, uint256 gasPrice, uint256 value)external view returns (bytes memory txdata){return EIP155Signer.sign(pubkey, secret, EIP155Signer.EthTx({nonce: nonce,gasPrice: gasPrice,gasLimit: 250000,to: msg.sender,value: value,data: "",chainId: block.chainid}));} Explore this more with Oasis docs on Sapphire Oasis Privacy Layer (OPL) This workflow demonstrates connecting Sapphire with Ethereum, BNB chain and other EVM networks to be able to add encrypted transactions and confidential state without moving the whole build away from the home network. Explore this more with Oasis docs on OPL Running a node As a decentralized network, Oasis encourages developers to help with decentralization by becoming a validator and/or running a ParaTime compute node (it can be Sapphire as well as Cipher or Emerald). Alternatively, devs can simply run consensus and/or ParaTime client node along with the web3 gateway to avoid public endpoints or possible malicious interactions. Explore this more with Oasis docs on running a node Key resources used for this tutorial which is must-check:Sapphire docsSapphire repositoryOasis playground for demo dAppsSapphire workshop in Oasis Academyhttps://medium.com/media/1f30f70b740196ca8a9bb6dcb28fd41e/href Have a question or need help? Join our Discord and head over to the #dev-central channel. Originally published at https://dev.to on August 27, 2025. Sapphire 101: A Technical Workshop For Blockchain Devs Part 3 was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this storyContinuing with Sapphire tutorial, we learnt in part 1 about Oasis architecture and confidential transaction, and in part 2 about signed view calls, frontend, and precompiles. #5: What to do next? This section will touch upon encryption & decryption, signing & verification, autonomous contracts, Oasis Privacy Layer (OPL), running nodes, etc. Encryption & Decryption We know now that end-to-end encryption is possible between user and smart contract where storage is on the public ledger in encrypted form. But, it is also possible to use X25519 key pairs inside a smart contract and derive shared secret on-chain. ECDH states that two people with their own key pairs, when they have each others public keys they can both derive the point, and nobody else can, unless one of the secrets gets leaked. Use cases Encrypted emitted events, stateless view calls Encrypted coupons, proxies, authentication, compliance Encryption (TypeScript) import * as sapphire from '@oasisprotocol/sapphire-paratime'const e2ePubKey = await e2e.getPublicKey();const box = sapphire.cipher.X25519DeoxysII.ephemeral(e2ePubKey);let {nonce, cipherText} = await box.encrypt(plaintextBytes);const nonceBytes32Hex = ethers.utils.hexlify(nonce) +"0000000000000000000000000000000000"; Decryption (Solidity) import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";contract E2EProxy {Sapphire.Curve25519PublicKey internal immutable publicKey;Sapphire.Curve25519SecretKey internal immutable privateKey;constructor (bytes memory extraEntropy) {(publicKey, privateKey) = Sapphire.generateCurve25519KeyPair(extraEntropy);}function getPublicKey() external view returns (bytes32) {return Sapphire.Curve25519PublicKey.unwrap(publicKey);}} import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";contract E2EProxy {function decrypt(bytes32 peerPublicKey, bytes32 nonce, bytes memory data)external{bytes32 sk = Sapphire.deriveSymmetricKey(Sapphire.Curve25519PublicKey.wrap(peerPublicKey),privateKey);bytes memory plaintext = Sapphire.decrypt(sk, nonce, data, "");}} Signing & Verification Contracts can generate key-pairs (Ed25519, X25519, Bitcoin & NIST) Signing with EcDSA and EdDSA There are various utilities for this. You can generate Ethereum addresses and sign transactions on-chain. You can verify WebAuthN / TouchID, using Ed25519 & EdDSA You can broadcast cross-chain without bridge dependency Signing (Solidity) import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";contract SigningExample {function sign(bytes32 hashed_message)external returns (bytes){Sapphire.SigningAlg alg =Sapphire.SigningAlg.Secp256k1PrehashedKeccak256;bytes memory pk;bytes memory sk;bytes memory digest = abi.encodePacked(hashed_message);Bytes memory entropy = Sapphire.randomBytes(32, "");(pk, sk) = Sapphire.generateSigningKeyPair(alg, entropy);return Sapphire.sign(alg, sk, digest, "");}} Verification (Solidity) import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";contract VerifyExample {function verify(bytes32 hashed_message, bytes memory signature)external returns (bool){Sapphire.SigningAlg alg =Sapphire.SigningAlg.Secp256k1PrehashedKeccak256;bytes memory digest = abi.encodePacked(hashed_message);return Sapphire.verify(alg, pk, digest, "", signature);}} On-chain Single Sign-On Viewing Keys — submitting an access token to view your data. Permits — providing access to specific functions (read/write). Daily Login with EIP-712: a. it is similar to permits but is application-specific b. it lets you sign a transaction once on a daily or weekly basis Explore this more with Oasis docs on Sapphire. Autonomous Contracts Using the key generation precompiles, Sapphire can generate Ethereum compatible accounts to pay their own gas — either on Sapphire or on other EVM compatible chains. Ethereum compatible key-generation & signing is included in the@oasisprotocol/sapphire-contracts package: EthereumUtils.sol — a, s = EthereumUtils.generateKeypair() EIP155Signer.sol — struct EIP155Signer.EthTx- EIP155Signer.sign(address,secret,tx) Ethereum Keypair Generation and Signing (Solidity) import '@oasisprotocol/sapphire-contracts/contracts/EthereumUtils.sol';contract KeypairExample {address pubkey;bytes32 secret;constructor () {(pubkey, secret) = EthereumUtils.generateKeypair();}function sign(bytes memory data)external view returns (SignatureRSV memory rsv){bytes32 digest = keccak256(data);rsv = EthereumUtils.sign(pubkey, secret, digest);}} Transaction Signing (Solidity) function signTx(uint64 nonce, uint256 gasPrice, uint256 value)external view returns (bytes memory txdata){return EIP155Signer.sign(pubkey, secret, EIP155Signer.EthTx({nonce: nonce,gasPrice: gasPrice,gasLimit: 250000,to: msg.sender,value: value,data: "",chainId: block.chainid}));} Explore this more with Oasis docs on Sapphire Oasis Privacy Layer (OPL) This workflow demonstrates connecting Sapphire with Ethereum, BNB chain and other EVM networks to be able to add encrypted transactions and confidential state without moving the whole build away from the home network. Explore this more with Oasis docs on OPL Running a node As a decentralized network, Oasis encourages developers to help with decentralization by becoming a validator and/or running a ParaTime compute node (it can be Sapphire as well as Cipher or Emerald). Alternatively, devs can simply run consensus and/or ParaTime client node along with the web3 gateway to avoid public endpoints or possible malicious interactions. Explore this more with Oasis docs on running a node Key resources used for this tutorial which is must-check:Sapphire docsSapphire repositoryOasis playground for demo dAppsSapphire workshop in Oasis Academyhttps://medium.com/media/1f30f70b740196ca8a9bb6dcb28fd41e/href Have a question or need help? Join our Discord and head over to the #dev-central channel. Originally published at https://dev.to on August 27, 2025. Sapphire 101: A Technical Workshop For Blockchain Devs Part 3 was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story

Sapphire 101: A Technical Workshop For Blockchain Devs Part 3

2025/08/29 13:54

Continuing with Sapphire tutorial, we learnt in part 1 about Oasis architecture and confidential transaction, and in part 2 about signed view calls, frontend, and precompiles.

#5: What to do next?

This section will touch upon encryption & decryption, signing & verification, autonomous contracts, Oasis Privacy Layer (OPL), running nodes, etc.

Encryption & Decryption

We know now that end-to-end encryption is possible between user and smart contract where storage is on the public ledger in encrypted form. But, it is also possible to use X25519 key pairs inside a smart contract and derive shared secret on-chain.

ECDH states that two people with their own key pairs, when they have each others public keys they can both derive the point, and nobody else can, unless one of the secrets gets leaked.

Use cases

  • Encrypted emitted events, stateless view calls
  • Encrypted coupons, proxies, authentication, compliance

Encryption (TypeScript)

import * as sapphire from '@oasisprotocol/sapphire-paratime'
const e2ePubKey = await e2e.getPublicKey();
const box = sapphire.cipher.X25519DeoxysII.ephemeral(e2ePubKey);
let {nonce, cipherText} = await box.encrypt(plaintextBytes);
const nonceBytes32Hex = ethers.utils.hexlify(nonce) +
"0000000000000000000000000000000000";

Decryption (Solidity)

import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";
contract E2EProxy {
Sapphire.Curve25519PublicKey internal immutable publicKey;
Sapphire.Curve25519SecretKey internal immutable privateKey;
constructor (bytes memory extraEntropy) {
(publicKey, privateKey) = Sapphire.generateCurve25519KeyPair(extraEntropy);
}
function getPublicKey() external view returns (bytes32) {
return Sapphire.Curve25519PublicKey.unwrap(publicKey);
}
}
import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";
contract E2EProxy {
function decrypt(bytes32 peerPublicKey, bytes32 nonce, bytes memory data)
external
{
bytes32 sk = Sapphire.deriveSymmetricKey(
Sapphire.Curve25519PublicKey.wrap(peerPublicKey),
privateKey);
bytes memory plaintext = Sapphire.decrypt(sk, nonce, data, "");
}
}

Signing & Verification

  • Contracts can generate key-pairs (Ed25519, X25519, Bitcoin & NIST)
  • Signing with EcDSA and EdDSA

There are various utilities for this.

  • You can generate Ethereum addresses and sign transactions on-chain.
  • You can verify WebAuthN / TouchID, using Ed25519 & EdDSA
  • You can broadcast cross-chain without bridge dependency

Signing (Solidity)

import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";
contract SigningExample {
function sign(bytes32 hashed_message)
external returns (bytes)
{
Sapphire.SigningAlg alg =
Sapphire.SigningAlg.Secp256k1PrehashedKeccak256;
bytes memory pk;
bytes memory sk;
bytes memory digest = abi.encodePacked(hashed_message);
Bytes memory entropy = Sapphire.randomBytes(32, "");
(pk, sk) = Sapphire.generateSigningKeyPair(alg, entropy);
return Sapphire.sign(alg, sk, digest, "");
}
}

Verification (Solidity)

import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";
contract VerifyExample {
function verify(bytes32 hashed_message, bytes memory signature)
external returns (bool)
{
Sapphire.SigningAlg alg =
Sapphire.SigningAlg.Secp256k1PrehashedKeccak256;
bytes memory digest = abi.encodePacked(hashed_message);
return Sapphire.verify(alg, pk, digest, "", signature);
}
}

On-chain Single Sign-On

  • Viewing Keys — submitting an access token to view your data.
  • Permits — providing access to specific functions (read/write).
  • Daily Login with EIP-712: a. it is similar to permits but is application-specific b. it lets you sign a transaction once on a daily or weekly basis

Explore this more with Oasis docs on Sapphire.

Autonomous Contracts

Using the key generation precompiles, Sapphire can generate Ethereum compatible accounts to pay their own gas — either on Sapphire or on other EVM compatible chains.

Ethereum compatible key-generation & signing is included in
the@oasisprotocol/sapphire-contracts package:

  • EthereumUtils.sol — a, s = EthereumUtils.generateKeypair()
  • EIP155Signer.sol — struct EIP155Signer.EthTx- EIP155Signer.sign(address,secret,tx)

Ethereum Keypair Generation and Signing (Solidity)

import '@oasisprotocol/sapphire-contracts/contracts/EthereumUtils.sol';
contract KeypairExample {
address pubkey;
bytes32 secret;
constructor () {
(pubkey, secret) = EthereumUtils.generateKeypair();
}
function sign(bytes memory data)
external view returns (SignatureRSV memory rsv)
{
bytes32 digest = keccak256(data);
rsv = EthereumUtils.sign(pubkey, secret, digest);
}
}

Transaction Signing (Solidity)

function signTx(uint64 nonce, uint256 gasPrice, uint256 value)
external view returns (bytes memory txdata)
{
return EIP155Signer.sign(pubkey, secret, EIP155Signer.EthTx({
nonce: nonce,
gasPrice: gasPrice,
gasLimit: 250000,
to: msg.sender,
value: value,
data: "",
chainId: block.chainid
}));
}

Explore this more with Oasis docs on Sapphire

Oasis Privacy Layer (OPL)

This workflow demonstrates connecting Sapphire with Ethereum, BNB chain and other EVM networks to be able to add encrypted transactions and
confidential state without moving the whole build away from the home network.

Explore this more with Oasis docs on OPL

Running a node

  • As a decentralized network, Oasis encourages developers to help with decentralization by becoming a validator and/or running a ParaTime compute node (it can be Sapphire as well as Cipher or Emerald).
  • Alternatively, devs can simply run consensus and/or ParaTime client node along with the web3 gateway to avoid public endpoints or possible malicious interactions.

Explore this more with Oasis docs on running a node

Key resources used for this tutorial which is must-check:
Sapphire docs
Sapphire repository
Oasis playground for demo dApps
Sapphire workshop in Oasis Academy

https://medium.com/media/1f30f70b740196ca8a9bb6dcb28fd41e/href

Have a question or need help? Join our Discord and head over to the #dev-central channel.

Originally published at https://dev.to on August 27, 2025.


Sapphire 101: A Technical Workshop For Blockchain Devs Part 3 was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

Market Opportunity
Particl Logo
Particl Price(PART)
$0.2639
$0.2639$0.2639
+0.57%
USD
Particl (PART) Live Price Chart
Disclaimer: The articles reposted on this site are sourced from public platforms and are provided for informational purposes only. They do not necessarily reflect the views of MEXC. All rights remain with the original authors. If you believe any content infringes on third-party rights, please contact [email protected] for removal. MEXC makes no guarantees regarding the accuracy, completeness, or timeliness of the content and is not responsible for any actions taken based on the information provided. The content does not constitute financial, legal, or other professional advice, nor should it be considered a recommendation or endorsement by MEXC.