@verifi-sdk/auth-aptos
v0.1.0
Published
Aptos authentication with SIWA (Sign In With Aptos) - Dual Ed25519 + BLS12-381 support. Lightweight extraction without heavy SDK dependencies.
Downloads
4
Readme
@verifi-sdk/auth-aptos
Lightweight Aptos authentication with SIWA (Sign In With Aptos) - Dual signature support: Ed25519 (wallet compatibility) + BLS12-381 (ZK-ready)
✨ Features
- 🔐 SIWA Standard - Full Sign In With Aptos implementation with domain separator
- 🪶 Lightweight - Only ~100kb (vs 800kb+ Aptos SDK)
- 🎯 Dual Signatures - Ed25519 (wallets) + BLS12-381 (ZK proofs)
- 📦 Framework-agnostic - Works with any JS framework
- 🔌 NO heavy deps - No
@aptos-labs/ts-sdkrequired - ⚡ Extracted code - Only what's needed for auth
📊 Size Comparison
| Package | Size | What's included |
|---------|------|-----------------|
| @aptos-labs/ts-sdk | ~800kb | Full SDK (transactions, API, etc.) |
| @verifi-sdk/auth-aptos | ~100kb | Auth only (SIWA + signatures) |
80% smaller 🎉
📦 Installation
npm install @verifi-sdk/auth-aptos
# or
pnpm add @verifi-sdk/auth-aptos🚀 Quick Start
Option 1: With Aptos Wallets (Ed25519)
import {
detectWallets,
signInWithWallet,
verifySignInSignature,
generateNonce,
createSignInMessage,
} from '@verifi-sdk/auth-aptos';
// 1. Detect wallets (Petra, Pontem, etc.)
const wallets = detectWallets();
const petra = wallets.find(w => w.name === 'Petra');
if (!petra) {
console.error('Petra wallet not found');
return;
}
// 2. Create SIWA input
const input = {
domain: 'app.verifi.wtf',
chainId: 'aptos:mainnet',
nonce: generateNonce(),
statement: 'Sign in to VeriFi Protocol',
uri: 'https://app.verifi.wtf',
};
// 3. Sign with wallet (Ed25519)
const output = await signInWithWallet(petra.wallet, input);
// 4. Verify signature
const result = await verifySignInSignature(output, {
expectedDomain: 'app.verifi.wtf',
expectedChainId: 'aptos:mainnet',
});
if (result.valid) {
console.log('✅ Authenticated:', result.address);
}Option 2: With BLS12-381 (ZK-ready)
import {
generateBLS12381KeyPair,
signInWithBLS,
verifySignInSignature,
generateNonce,
} from '@verifi-sdk/auth-aptos';
// 1. Generate BLS12-381 keypair
const keyPair = generateBLS12381KeyPair();
console.log('Address:', keyPair.address);
// 2. Create SIWA input
const input = {
domain: 'app.verifi.wtf',
address: keyPair.address,
chainId: 'aptos:mainnet',
nonce: generateNonce(),
statement: 'Sign in with ZK-ready signature',
};
// 3. Sign with BLS12-381
const output = await signInWithBLS(input, keyPair.privateKey);
// 4. Verify
const result = await verifySignInSignature(output);
if (result.valid) {
console.log('✅ ZK-ready auth:', result.address);
}🔥 Advanced: Batch Sign-In (BLS12-381)
import {
generateBLS12381KeyPair,
batchSignIn,
aggregateBatchSignatures,
verifyAggregatedSignature,
} from '@verifi-sdk/auth-aptos';
// Generate multiple keypairs
const user1 = generateBLS12381KeyPair();
const user2 = generateBLS12381KeyPair();
const user3 = generateBLS12381KeyPair();
const inputs = [
{ domain: 'app.verifi.wtf', address: user1.address, nonce: generateNonce(), chainId: 'aptos:mainnet' },
{ domain: 'app.verifi.wtf', address: user2.address, nonce: generateNonce(), chainId: 'aptos:mainnet' },
{ domain: 'app.verifi.wtf', address: user3.address, nonce: generateNonce(), chainId: 'aptos:mainnet' },
];
// Batch sign
const outputs = await batchSignIn(inputs, [user1.privateKey, user2.privateKey, user3.privateKey]);
// Aggregate signatures (O(1) verification!)
const aggSig = await aggregateBatchSignatures(outputs);
// Verify aggregated signature
const result = await verifyAggregatedSignature(aggSig, outputs);
console.log('Batch verified:', result.valid);🏗️ Architecture
What's Extracted (vs Full SDK)
| Component | Extracted | Source |
|-----------|-----------|--------|
| Ed25519 | ✅ | @noble/curves (~40kb) |
| BLS12-381 | ✅ | @noble/bls12-381 (~30kb) |
| SIWA Logic | ✅ | @aptos-labs/siwa (~20kb) |
| Wallet Types | ✅ | @aptos-labs/wallet-standard (~10kb) |
| API Client | ❌ | Not needed |
| Transactions | ❌ | Not needed |
| Framework | ❌ | Not needed |
Total: ~100kb (only auth essentials)
SIWA Domain Separator
Implements Aptos SIWA standard with domain separator:
signing_message = SHA3-256("SIGN_IN_WITH_APTOS::") + message_bytesThis prevents signature collision across different protocols.
🔌 Backend Integration
Next.js API Route
// app/api/auth/siwa/verify/route.ts
import { verifySignInSignature, initJWE, encryptSession } from '@verifi-sdk/auth-aptos';
initJWE({ secret: process.env.JWT_SECRET! });
export async function POST(req: Request) {
const output = await req.json();
// Verify SIWA signature
const result = await verifySignInSignature(output, {
expectedDomain: 'app.verifi.wtf',
expectedChainId: 'aptos:mainnet',
});
if (!result.valid) {
return Response.json({ error: 'Invalid signature' }, { status: 401 });
}
// Create encrypted session
const token = await encryptSession({
address: result.address!,
publicKey: typeof output.publicKey === 'string' ? output.publicKey : '',
loginTime: Date.now(),
});
// Set HTTP-only cookie
const response = Response.json({ success: true, address: result.address });
response.headers.set('Set-Cookie', `auth_token=${token}; HttpOnly; Secure; SameSite=Lax; Max-Age=86400; Path=/`);
return response;
}Express.js
import express from 'express';
import { verifySignInSignature, initJWE, encryptSession } from '@verifi-sdk/auth-aptos';
const app = express();
app.use(express.json());
initJWE({ secret: process.env.JWT_SECRET! });
app.post('/api/auth/siwa/verify', async (req, res) => {
const result = await verifySignInSignature(req.body);
if (!result.valid) {
return res.status(401).json({ error: 'Invalid signature' });
}
const token = await encryptSession({
address: result.address!,
publicKey: req.body.publicKey,
loginTime: Date.now(),
});
res.cookie('auth_token', token, {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 86400000,
});
res.json({ success: true, address: result.address });
});📚 API Reference
Signatures
Ed25519 (Wallet Compatible)
generateEd25519KeyPair(): Ed25519KeyPair
signEd25519(message, privateKey): Promise<Ed25519Signature>
verifyEd25519(signature, message, publicKey): Promise<boolean>BLS12-381 (ZK-Ready)
generateBLS12381KeyPair(): BLS12381KeyPair
signBLS12381(message, privateKey): Promise<BLS12381Signature>
verifyBLS12381(signature, message, publicKey): Promise<boolean>
aggregateBLSSignatures(signatures): Uint8Array
aggregateBLSPublicKeys(publicKeys): Uint8ArraySIWA
createSignInMessage(input: AptosSignInInput): string
createSignInSigningMessage(message: string): Uint8Array
generateNonce(): string
signInWithEd25519(input, privateKey): Promise<AptosSignInOutput>
signInWithBLS(input, privateKey): Promise<AptosSignInOutput>
verifySignInSignature(output, options?): Promise<SIWAVerificationResult>Wallet Adapter
detectWallets(): AptosWalletProvider[]
getWallet(name: string): AptosWallet | null
signInWithWallet(wallet, input): Promise<AptosSignInOutput>
checkWalletCapabilities(wallet): WalletCapabilities🔗 Related Packages
@verifi-sdk/auth-core- Framework-agnostic auth core@verifi-sdk/auth-solana- Solana authentication (coming soon)@verifi-sdk/auth-evm- EVM authentication (coming soon)
📝 License
MIT © edsphinx
🤝 Contributing
Contributions welcome! See CONTRIBUTING.md
🐛 Issues
Found a bug? Report it
