Cosmic Cipher Password Generator
Learn how to build a secure password generator using SpaceComputer Orbitport's cosmic randomness for enterprise-grade security
This recipe demonstrates how to build a secure password generator using SpaceComputer Orbitport's cTRNG (cosmic True Random Number Generator) service. Unlike traditional password generators that rely on pseudo-random algorithms, this implementation uses genuine cosmic randomness from satellite instrumentation to create truly unpredictable passwords.
Video Walkthrough
Follow along with the video walkthrough of this recipe: Generate a Secure Password Using Cosmic Entropy
Prerequisites
- TypeScript/JavaScript knowledge
- Next.js or React application
- API access to SpaceComputer Orbitport (Get your API access key here)
- Understanding of password security requirements
What You'll Build
A secure password generator that:
- Uses cosmic randomness from satellite instrumentation for true entropy
- Implements flexible password generation with customizable character sets
- Provides client-side password generation with server-side randomness
- Includes fallback mechanisms for offline resilience
- Offers verifiable randomness with seed display
Architecture Pattern Rationale
This recipe implements a Hybrid Randomness Pattern which is ideal for password generation:
- Cosmic Entropy: Server-side retrieval of truly random seeds from space
- Local Generation: Client-side password crafting for flexibility and privacy
- Fallback Resilience: Node.js crypto fallback when cosmic randomness is unavailable
- Verifiable Randomness: Users can verify the cosmic origin of their passwords
- Customizable Logic: Easy to modify character sets and generation rules
Implementation Steps
1. Environment Configuration
Set up your environment variables:
# .env.local
ORBITPORT_CLIENT_ID=your_client_id
ORBITPORT_CLIENT_SECRET=your_client_secret
ORBITPORT_AUTH_URL=https://auth.spacecomputer.io
ORBITPORT_API_URL=https://op.spacecomputer.io2. Authentication Setup
Design Rationale for Production
Server-side authentication is critical for password generation because:
- Security: API credentials are never exposed to client-side code, preventing credential theft
- Token Management: Centralized token lifecycle management reduces security vulnerabilities
- Rate Limiting: Server-side control allows for proper API rate limiting and abuse prevention
- Audit Trail: All password generation requests can be logged and monitored
- Scalability: Multiple server instances can share the same authentication logic
Create a centralized authentication utility in lib/auth.ts:
// lib/auth.ts
import { NextApiRequest, NextApiResponse } from "next";
import { parseToken, decrypt, encrypt } from "./crypto"; // You'll need to implement these
const TOKEN_EXPIRE_BUFFER = 300; // 5 minutes buffer
async function generateAccessToken(): Promise<string | null> {
const clientId = process.env.ORBITPORT_CLIENT_ID;
const clientSecret = process.env.ORBITPORT_CLIENT_SECRET;
const authUrl = process.env.ORBITPORT_AUTH_URL;
if (!clientId || !clientSecret || !authUrl) {
throw new Error("Missing Orbitport authentication configuration");
}
try {
const response = await fetch(`${authUrl}/oauth/token`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
client_id: clientId,
client_secret: clientSecret,
audience: "https://op.spacecomputer.io/api",
grant_type: "client_credentials",
}),
});
if (!response.ok) {
throw new Error("Failed to get access token");
}
const data = await response.json();
return data.access_token;
} catch (error) {
console.error("Error getting access token:", error);
return null;
}
}
export async function getValidToken(
req: NextApiRequest,
res: NextApiResponse
): Promise<string | null> {
try {
const encryptedToken = getEncryptedTokenFromCookies(req);
let accessToken: string | null = null;
if (encryptedToken) {
const decrypted = decrypt(encryptedToken);
const parsed = parseToken(decrypted);
if (parsed) {
const now = Math.floor(Date.now() / 1000);
// Only use token if not expired and not about to expire
if (parsed.exp > now + TOKEN_EXPIRE_BUFFER) {
accessToken = parsed.access_token;
}
}
}
// If no valid token, generate a new one
if (!accessToken) {
accessToken = await generateAccessToken();
if (!accessToken) {
console.error("Failed to get new access token");
return null;
}
const parsed = parseToken(accessToken);
if (!parsed) {
console.error("Failed to parse new token");
return null;
}
setEncryptedTokenCookie(res, accessToken, parsed.exp);
}
return accessToken;
} catch (error) {
console.error("Error in getValidToken:", error);
return null;
}
}Token Expiry Management Rationale
The TOKEN_EXPIRE_BUFFER (5-minute buffer) is essential for production because:
- Proactive Refresh: Tokens are refreshed before they expire, preventing user-facing errors
- Graceful Degradation: If token refresh fails, the buffer provides time for fallback mechanisms
- Load Distribution: Staggered token refreshes prevent all users from hitting the auth endpoint simultaneously
- Security: Reduces the window where expired tokens might be used
- User Experience: Eliminates authentication timeouts during active user sessions
3. API Route for Random Seeds
Create an API endpoint in pages/api/random.ts with fallback support:
// pages/api/random.ts
import { NextApiRequest, NextApiResponse } from "next";
import { getValidToken } from "@/lib/auth";
import crypto from "crypto";
const ORBITPORT_API_URL = process.env.ORBITPORT_API_URL;
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
let usedFallback = false;
let data: any = null;
try {
if (req.method !== "GET") {
return res.status(405).json({ message: "Method not allowed" });
}
if (!process.env.ORBITPORT_API_URL) {
return res.status(500).json({ message: "Missing Orbitport API URL" });
}
// Get valid token using our auth utility
const accessToken = await getValidToken(req, res);
if (!accessToken) {
return res.status(401).json({ message: "Authentication failed" });
}
// Call downstream API with access token
const response = await fetch(`${ORBITPORT_API_URL}/api/v1/services/trng`, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
if (!response.ok) {
const errorText = await response.text();
console.error("Orbitport API error:", errorText);
throw new Error(`API request failed: ${response.status}`);
}
data = await response.json();
} catch (error) {
console.warn("Using fallback random generation:", error);
usedFallback = true;
// Fallback to Node.js crypto for offline resilience
const fallbackSeed = crypto.randomBytes(32).toString("hex");
data = {
service: "fallback",
src: "node-crypto",
data: fallbackSeed,
signature: {
value: "fallback-signature",
pk: "fallback-key",
},
};
}
return res.status(200).json({
...data,
usedFallback,
});
}API Route Design Rationale
Using a server-side API route with fallback provides:
- Security: Access tokens never leave your server, preventing token exposure
- Error Handling: Centralized error handling with proper HTTP status codes
- Fallback Resilience: Node.js crypto ensures password generation works even when cosmic randomness is unavailable
- Rate Limiting: Implement per-user rate limiting to prevent API abuse
- Monitoring: Track usage patterns and implement alerting for production issues
- Compliance: Meet enterprise security requirements for external API access
4. Password Generation Logic
Create the core password generation logic in lib/password-generator.ts:
// lib/password-generator.ts
interface GenerateParams {
length: number;
minUpper: number;
minLower: number;
minNumbers: number;
minSymbols: number;
includeUpper: boolean;
includeLower: boolean;
includeNumbers: boolean;
includeSymbols: boolean;
}
const CHARSETS = {
uppercase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
lowercase: "abcdefghijklmnopqrstuvwxyz",
numbers: "0123456789",
symbols: "!@#$%^&*+-=",
};
// Creates a deterministic random generator from cosmic seed
function createRandomGenerator(seed: string) {
const seedBytes = new Uint8Array(Buffer.from(seed, "hex"));
let position = 0;
return (length: number): Uint8Array => {
const result = new Uint8Array(length);
for (let i = 0; i < length; i++) {
result[i] = seedBytes[position % seedBytes.length];
position++;
}
return result;
};
}
export function generatePasswordFromSeed(
seed: string,
params: GenerateParams
): string {
const randomValues = createRandomGenerator(seed);
const {
length,
minUpper,
minLower,
minNumbers,
minSymbols,
includeUpper,
includeLower,
includeNumbers,
includeSymbols,
} = params;
// Build character sets based on user selection
const availableCharsets: { [key: string]: string } = {};
if (includeUpper) availableCharsets.uppercase = CHARSETS.uppercase;
if (includeLower) availableCharsets.lowercase = CHARSETS.lowercase;
if (includeNumbers) availableCharsets.numbers = CHARSETS.numbers;
if (includeSymbols) availableCharsets.symbols = CHARSETS.symbols;
// Generate password meeting minimum requirements
let password = "";
if (includeUpper) {
for (let i = 0; i < minUpper; i++) {
password +=
availableCharsets.uppercase[
randomValues(1)[0] % availableCharsets.uppercase.length
];
}
}
if (includeLower) {
for (let i = 0; i < minLower; i++) {
password +=
availableCharsets.lowercase[
randomValues(1)[0] % availableCharsets.lowercase.length
];
}
}
if (includeNumbers) {
for (let i = 0; i < minNumbers; i++) {
password +=
availableCharsets.numbers[
randomValues(1)[0] % availableCharsets.numbers.length
];
}
}
if (includeSymbols) {
for (let i = 0; i < minSymbols; i++) {
password +=
availableCharsets.symbols[
randomValues(1)[0] % availableCharsets.symbols.length
];
}
}
// Fill remaining length with random chars
const allAvailableChars = Object.values(availableCharsets).join("");
const remainingLength = length - password.length;
for (let i = 0; i < remainingLength; i++) {
password +=
allAvailableChars[randomValues(1)[0] % allAvailableChars.length];
}
// Fisher-Yates shuffle using cosmic seed for randomness
const passwordArray = password.split("");
for (let i = passwordArray.length - 1; i > 0; i--) {
const j = randomValues(1)[0] % (i + 1);
[passwordArray[i], passwordArray[j]] = [passwordArray[j], passwordArray[i]];
}
return passwordArray.join("");
}Password Generation Rationale
The password generation logic provides production benefits through:
- Cosmic Entropy: Uses genuine randomness from space, not predictable algorithms
- Deterministic Mapping: Same seed always produces the same password for verification
- Requirement Fulfillment: Guarantees minimum character requirements are met
- Fair Distribution: Fisher-Yates shuffle ensures uniform character distribution
- Extensibility: Easy to add new character sets or modify generation rules
- Client-Side Privacy: Password generation happens locally, not on external servers
5. Client-Side Hook
Create a custom React hook in hooks/useOrbitport.ts:
// hooks/useOrbitport.ts
import { useCallback } from "react";
interface RandomSeedResponse {
service: string;
src: string;
data: string;
signature: {
value: string;
pk: string;
};
usedFallback: boolean;
}
export function useOrbitport() {
const getRandomSeed = useCallback(async (): Promise<RandomSeedResponse> => {
try {
const response = await fetch("/api/random");
if (!response.ok) {
throw new Error("Failed to get random seed");
}
const data = await response.json();
return data;
} catch (error) {
console.error("Error getting random seed:", error);
throw error;
}
}, []);
return {
getRandomSeed,
};
}React Hook Design Rationale
Custom hooks provide production benefits through:
- Reusability: The same hook can be used across multiple components
- State Management: Centralized loading and error states for better UX
- Testing: Easier to unit test business logic separately from UI components
- Performance:
useCallbackprevents unnecessary re-renders and API calls - Error Boundaries: Consistent error handling across the application
- Type Safety: TypeScript interfaces ensure data consistency
6. Usage Example
Here's how to use the password generator in your application:
import { useOrbitport } from "@/hooks/useOrbitport";
import { generatePasswordFromSeed } from "@/lib/password-generator";
function PasswordGenerator() {
const { getRandomSeed } = useOrbitport();
const [password, setPassword] = useState<string>("");
const [seed, setSeed] = useState<string>("");
const [usedFallback, setUsedFallback] = useState<boolean>(false);
const handleGenerate = async () => {
try {
// Fetch cosmic seed from API
const seedResult = await getRandomSeed();
// Generate password client-side using the seed
const generatedPassword = generatePasswordFromSeed(seedResult.data, {
length: 16,
minUpper: 2,
minLower: 2,
minNumbers: 2,
minSymbols: 2,
includeUpper: true,
includeLower: true,
includeNumbers: true,
includeSymbols: true,
});
setPassword(generatedPassword);
setSeed(seedResult.data);
setUsedFallback(seedResult.usedFallback);
} catch (error) {
console.error("Failed to generate password:", error);
}
};
return (
<div>
<button onClick={handleGenerate}>Generate Cosmic Password</button>
{password && (
<div>
<p>
<strong>Password:</strong> {password}
</p>
<p>
<strong>Cosmic Seed:</strong> {seed}
</p>
{usedFallback && (
<p>
<em>Note: Used fallback randomness</em>
</p>
)}
</div>
)}
</div>
);
}Password Generation Usage Rationale
The password generator example demonstrates production-ready patterns:
- Verifiable Randomness: Users can see the cosmic seed that generated their password
- Fallback Transparency: Clear indication when fallback randomness is used
- Error Handling: Try-catch blocks prevent application crashes from API failures
- User Feedback: Clear display of generated password and source randomness
- Extensibility: Easy to modify character requirements or add new features
- Security: Password generation happens client-side for privacy
Key Benefits
- True Randomness: Leverages cosmic radiation for unbiased password generation
- Security: Server-side token management with client-side password generation
- Reliability: Fallback mechanisms ensure password generation always works
- Verifiability: Users can verify the cosmic origin of their passwords
- Flexibility: Customizable character sets and generation rules
- Privacy: Password generation happens locally, not on external servers
Use Cases
- Enterprise Security: Generate secure passwords for corporate accounts
- Personal Use: Create strong passwords for personal accounts
- Developer Tools: Integrate into password management systems
- Security Audits: Generate test passwords with verifiable randomness
- Compliance: Meet security requirements for password generation
Production Considerations
Enterprise-Grade Password Security
This recipe follows production-ready patterns essential for secure password generation:
Security First Approach
- Cosmic Entropy: Uses genuine randomness from space, not predictable algorithms
- Credential Isolation: API keys are never exposed to client-side code
- Token Encryption: Access tokens are encrypted in cookies with proper expiry management
- Client-Side Generation: Passwords are generated locally for privacy
Reliability & Performance
- Fallback Resilience: Node.js crypto ensures password generation works offline
- Proactive Token Refresh: Eliminates authentication timeouts during user sessions
- Error Handling: Graceful degradation when external services are unavailable
- Performance: Efficient password generation with minimal computational overhead
Scalability & Monitoring
- Centralized Logic: Single source of truth for authentication across all server instances
- Performance Metrics: Track API response times and failure rates
- Alerting: Proactive notifications for authentication failures or rate limit issues
- Horizontal Scaling: Authentication logic works seamlessly across multiple servers
Compliance & Governance
- Data Privacy: No sensitive data leaves your infrastructure
- Audit Trails: Complete logging for compliance and security investigations
- Rate Limiting: Prevent abuse and ensure fair usage across all users
- Verifiable Randomness: Users can verify the cosmic origin of their passwords
Next Steps
- Implement the crypto utility functions for token encryption/decryption
- Add password strength validation and entropy calculation
- Consider implementing password history and reuse prevention
- Explore other Orbitport services like spaceTEE for secure computation
- Add support for passphrase generation and mnemonic phrases
Resources
Cosmic Randomness in Web3 Applications
Learn how to implement true cosmic randomness in your Web3 applications using SpaceComputer Orbitport's cTRNG service
Secure Nonces for Sign In with Ethereum
Learn how to generate secure nonces for Sign In with Ethereum using verifiable cosmic randomness from SpaceComputer Orbitport