Skip to main content

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: localStorage for pubkey, hash, checkHash

How It Works

  1. User clicks "Connect Wallet" on your dApp
  2. Redirects to https://wallet.analos.io/connect?url=...
  3. User enters password → decrypts keypair
  4. On success: localStorage updated → redirect back → location.reload()
  5. 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.origin to 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

RuleWhy
Never log passwordsClient-side only
Use HTTPSPrevent MITM
Validate checkHashPrevent brute-force
Clear on logoutRemove from localStorage
No server keysFully decentralized

Connect. Secure. Build.