Wallet Connect
Secure Decentralized Authentication
Wallet Connect allows users to securely connect their ANALOS wallet to dApps using password-protected encrypted keypairs stored locally. This system uses AES encryption with a SHA-256 password hash and double verification via a check hash, ensuring no private keys are ever exposed.
- URL: wallet.analos.io
- Security: Client-side decryption, zero server storage
- Flow: Redirect → Password → Decrypt → Connect
- Storage:
localStorageforpubkey,hash,checkHash
How It Works
- User clicks "Connect Wallet" on your dApp
- Redirects to
https://wallet.analos.io/connect?url=... - User enters password → decrypts keypair
- On success:
localStorageupdated → redirect back →location.reload() - dApp reads
localStorage.getItem('pubkey')to identify user
Integration Guide
1. Add Connect Button
<button on:click={openWalletConnect}>
Connect Wallet
</button>
<script>
const openWalletConnect = () => {
const currentUrl = encodeURIComponent(location.origin);
window.location.replace(`https://wallet.analos.io/connect?url=${currentUrl}`);
};
</script>
Note: Always use
location.originto support subdomains.
2. Handle Redirect & Password Modal (Svelte Example)
Use the provided Svelte component to handle post-redirect flow.
<script context="module" lang="ts">
import { goto } from "$app/navigation";
import { onMount } from "svelte";
import { fade } from "svelte/transition";
import { getAddressFromPublicKey } from "@solana/kit";
import { getKeyPairFromHashWithPassword, validatePassword } from "$lib/services/solana";
</script>
<script lang="ts">
export let isOpen: boolean = false;
let password: string = '';
let hash: string = '';
let checkHash: string = '';
let isValidPassword: boolean = false;
const closeModal = () => { isOpen = false; };
onMount(() => {
const params = new URLSearchParams(location.hash.replace('#', '?'));
hash = params.get('h') || '';
checkHash = params.get('ch') || '';
if (hash && checkHash) {
isOpen = true;
goto('/');
}
});
const connectWallet = async () => {
if (!isValidPassword) return;
const keypair = await getKeyPairFromHashWithPassword(hash, password);
const pubkey = await getAddressFromPublicKey(keypair.publicKey);
localStorage.setItem('pubkey', pubkey);
localStorage.setItem('hash', hash);
localStorage.setItem('checkHash', checkHash);
isOpen = false;
location.reload();
};
const checkPassword = () => {
isValidPassword = validatePassword(hash, checkHash, password);
};
</script>
{#if isOpen}
<div class="modal-overlay" in:fade out:fade on:click|self={closeModal}>
<div class="connect-modal">
<button class="modal-close" on:click={closeModal}>×</button>
<div class="modal-header">
<h3 class="modal-title">Wallet Connect</h3>
</div>
<form on:submit|preventDefault={connectWallet}>
<div class="form-group">
<label class="form-label">Enter your password</label>
<input
type="password"
class="form-input"
bind:value={password}
on:input={checkPassword}
placeholder="••••••••"
/>
</div>
<button
type="submit"
class="execute-btn"
disabled={!isValidPassword}
>
Connect wallet
</button>
</form>
</div>
</div>
{/if}
3. Security Functions (CryptoJS + Solana)
Add these utilities to $lib/services/solana.ts:
import CryptoJS from 'crypto-js';
import { Keypair } from '@solana/web3.js';
export const getKeyFromHashWithPassword = (hash: string, password: string): string => {
const passwordHash = CryptoJS.SHA256(password).toString();
const decrypted = CryptoJS.AES.decrypt(hash, passwordHash);
return decrypted.toString(CryptoJS.enc.Utf8);
};
export const getKeyPairFromHashWithPassword = async (hash: string, password: string): Promise<Keypair> => {
const secretKeyStr = getKeyFromHashWithPassword(hash, password);
const secretKey = Uint8Array.from(JSON.parse(secretKeyStr));
return Keypair.fromSecretKey(secretKey);
};
export const validatePassword = (hash: string, checkHash: string, password: string): boolean => {
try {
const keyHash = CryptoJS.SHA256(getKeyFromHashWithPassword(hash, password)).toString();
return keyHash === checkHash;
} catch {
return false;
}
};
Dependencies:
npm install crypto-js @solana/web3.js
Check Connection Status
const isConnected = () => {
return !!localStorage.getItem('pubkey');
};
const getPublicKey = (): string | null => {
return localStorage.getItem('pubkey');
};
const disconnect = () => {
localStorage.removeItem('pubkey');
localStorage.removeItem('hash');
localStorage.removeItem('checkHash');
location.reload();
};
Security Best Practices
| Rule | Why |
|---|---|
| Never log passwords | Client-side only |
| Use HTTPS | Prevent MITM |
Validate checkHash | Prevent brute-force |
| Clear on logout | Remove from localStorage |
| No server keys | Fully decentralized |
Connect. Secure. Build.