#!/usr/bin/env node
/**
* Test ANProto signatures
*/
import crypto from 'hypercore-crypto'
import b4a from 'b4a'
const BASE_URL = 'http://localhost:5005/git';
async function test() {
console.log('🧪 Testing ANProto signatures...\n');
// Step 1: Generate identity
console.log('1. Generating identity...');
const genResponse = await fetch(`${BASE_URL}/api/identity/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
if (!genResponse.ok) {
console.error('❌ Failed to generate identity:', genResponse.status);
process.exit(1);
}
const identity = await genResponse.json();
const publicKey = identity.publicKey;
const keypair = identity.keypair;
const secretKeyB64 = keypair.substring(44, 132);
console.log('✓ Identity generated:', publicKey.substring(0, 8) + '...');
console.log(' Keypair length:', keypair.length);
// Step 2: Get challenge
console.log('\n2. Getting challenge...');
const challengeResponse = await fetch(`${BASE_URL}/api/auth/challenge`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ context: 'test' })
});
if (!challengeResponse.ok) {
console.error('❌ Failed to get challenge:', challengeResponse.status);
process.exit(1);
}
const challengeData = await challengeResponse.json();
console.log('✓ Challenge received:', challengeData.challengeId.substring(0, 8) + '...');
console.log(' Challenge:', challengeData.challenge.substring(0, 20) + '...');
console.log(' Expires in:', Math.floor((challengeData.expiresAt - Date.now()) / 1000), 'seconds');
// Step 3: Sign challenge
console.log('\n3. Signing challenge...');
const secretKeyBytes = b4a.from(secretKeyB64, 'base64');
const challengeBytes = b4a.from(challengeData.challenge, 'utf8');
// Use 2-argument form which returns the signature
const signature = crypto.sign(challengeBytes, secretKeyBytes);
const signatureB64 = b4a.toString(signature, 'base64');
console.log('✓ Signature created:', signatureB64.substring(0, 20) + '...');
console.log(' Signature length:', signatureB64.length, 'chars');
// Step 4: Test with signature
console.log('\n4. Testing with signature...');
const authResponse = await fetch(`${BASE_URL}/api/user/identities`, {
headers: {
'X-Wirecore-PublicKey': publicKey,
'X-Wirecore-Signature': signatureB64,
'X-Wirecore-Challenge': challengeData.challengeId
}
});
console.log(' Status:', authResponse.status, authResponse.statusText);
if (authResponse.ok) {
const data = await authResponse.json();
console.log('✅ Authenticated with signature!');
console.log(' User ID:', data.user?.userId);
console.log(' Identities:', data.identities.length);
} else {
const errorText = await authResponse.text();
console.error('❌ Signature authentication failed!');
console.error(' Error:', errorText);
process.exit(1);
}
// Step 5: Test legacy (without signature)
console.log('\n5. Testing legacy mode (no signature)...');
const legacyResponse = await fetch(`${BASE_URL}/api/user/identities`, {
headers: {
'X-Wirecore-PublicKey': publicKey
}
});
console.log(' Status:', legacyResponse.status, legacyResponse.statusText);
if (legacyResponse.ok) {
console.log('✓ Legacy mode still works');
} else {
console.log('✗ Legacy mode disabled');
}
console.log('\n✅ ANProto signatures working!');
}
test().catch(err => {
console.error('\n❌ Test failed:', err.message);
console.error(err.stack);
process.exit(1);
});