/scrypt

scrypt

Créé en 2009 par Colin PercivalRFC 7914

Sécurisé - Memory-Hard FunctionMemory-hardCrypto-monnaies
13 ans
Crypto-monnaies

💎 PIONNIER MEMORY-HARD - RÉSISTANCE ASIC PROUVÉE

scrypt révolutionna la cryptographie moderne en 2009 avec sa fonction memory-hard. Résistance GPU/ASIC démontrée par 13 années de crypto-monnaies (Litecoin, Dogecoin), protection équitable du mining et standard IETF RFC 7914.

Paramètres scrypt - Configuration Memory-Hard

ParamètreDescriptionValeurs TypiquesImpact Sécurité
NCoût CPU/mémoire2^14 à 2^20Résistance ASIC
rTaille bloc8 (standard)Usage mémoire
pParallélisme1-4Multi-threading
keylenLongueur sortie32-64 bytesSécurité hash
Formule Mémoire : 128 × N × r bytes

La consommation mémoire élevée est la clé de la résistance scrypt. N=32768, r=8 → 256 MiB minimum, rendant les attaques matérielles spécialisées coûteuses.

Adoption Crypto-monnaies - Succès Historique

Crypto-monnaieConfigurationStatutNote
Litecoin (LTC)N=1024, r=1, p=1Actif depuis 2011Premier succès
Dogecoin (DOGE)N=1024, r=1, p=1ActifFork Litecoin
Vertcoin (VTC)N=1024, r=1, p=1ActifASIC-resistant
Applications modernesN=32768, r=8, p=1RecommandéHaute sécurité
Litecoin Legacy

Litecoin (2011) fut la première crypto-monnaie majeure à adopter scrypt, démocratisant le mining avec des GPU standard vs Bitcoin ASIC.

ASIC Resistance

13 années de résistance prouvée aux ASIC miniers, maintenant l'équité du mining décentralisé.

Avantages Memory-Hard Function

Memory-Hard Function

Maximum

Coût mémoire élevé (128×N×r bytes) rend les attaques GPU/ASIC économiquement non-viables

Résistance ASIC Prouvée

Excellent

10+ années d'usage en crypto-monnaies, protection mineurs individuels démontrée

Paramètres Flexibles

Important

Configuration N, r, p adaptable selon besoins sécurité vs performance

Standard IETF RFC 7914

Référence

Spécification officielle, implémentations interopérables multi-langages

Mécanismes de Résistance

💾 Memory-Hard
  • • Consommation RAM obligatoire (128×N×r)
  • • Accès mémoire fréquents et aléatoires
  • • Goulot d'étranglement bande passante
  • • Coût matériel spécialisé prohibitif
⚡ Time-Memory Tradeoff
  • • Réduire RAM → augmenter calculs
  • • Paramètres configurables N, r, p
  • • Évolutivité selon hardware disponible
  • • Équilibre sécurité/performance

Applications et Cas d'Usage

Crypto-monnaies

Litecoin (LTC) mining
Dogecoin (DOGE) network
Altcoins ASIC-resistant
Proof-of-Work équitable
Mining pools décentralisés

Applications Sécurisées

Key derivation haute sécurité
Wallet crypto-monnaies
Password hashing robuste
Cold storage protection
Hardware security modules

Enterprise Security

Serveurs haute sécurité
Archives long-terme
Systèmes de backup
Identity management
Compliance réglementaire

Recherche & R&D

Cryptanalyse résistance
Benchmarks performance
Nouveaux algorithmes
Academic research
Security auditing
Adoption Industrielle
Litecoin
Crypto leader
Tarsnap
Backup service
Django
Web framework
RFC 7914
IETF standard

Implémentations Memory-Hard Production

Code Production Memory-Hard

Implémentations complètes avec configurations adaptatives, benchmarks et simulation mining crypto-monnaie pour usage production.

Node.js - Manager scrypt Adaptatif

const crypto = require('crypto');
const scrypt = require('scrypt');

// ✅ SCRYPT - Configuration Production 2024
class ScryptManager {
  constructor() {
    // Configurations recommandées selon usage
    this.configs = {
      // Applications web interactives
      interactive: {
        N: 16384,      // 2^14
        r: 8,          // Block size factor
        p: 1,          // Parallelization
        keylen: 64,    // Output length
        memory: '128MB',
        time: '~200ms'
      },
      
      // Services backend
      server: {
        N: 32768,      // 2^15
        r: 8,
        p: 1,
        keylen: 64,
        memory: '256MB',
        time: '~500ms'
      },
      
      // Haute sécurité (crypto-monnaies style)
      high_security: {
        N: 1048576,    // 2^20
        r: 8,
        p: 1,
        keylen: 64,
        memory: '1GB',
        time: '~5s'
      }
    };
  }

  // Hash avec scrypt (Node.js crypto natif)
  async hashPassword(password, salt = null, config = 'server') {
    const params = this.configs[config];
    
    if (!salt) {
      salt = crypto.randomBytes(32);
    }
    
    const startTime = Date.now();
    
    try {
      const derived = await new Promise((resolve, reject) => {
        crypto.scrypt(password, salt, params.keylen, {
          N: params.N,
          r: params.r,
          p: params.p,
          maxmem: params.N * params.r * 128 * 2 // Sécurité mémoire
        }, (err, derivedKey) => {
          if (err) reject(err);
          else resolve(derivedKey);
        });
      });
      
      const duration = Date.now() - startTime;
      
      return {
        hash: derived.toString('hex'),
        salt: salt.toString('hex'),
        algorithm: 'scrypt',
        params: params,
        config: config,
        duration: `${duration}ms`,
        memory_usage: this.calculateMemoryUsage(params),
        timestamp: new Date().toISOString()
      };
      
    } catch (error) {
      throw new Error(`scrypt hashing failed: ${error.message}`);
    }
  }

  // Vérification sécurisée
  async verifyPassword(password, expectedHash, salt, config = 'server') {
    try {
      const result = await this.hashPassword(password, Buffer.from(salt, 'hex'), config);
      
      // Comparaison temps constant
      const expected = Buffer.from(expectedHash, 'hex');
      const computed = Buffer.from(result.hash, 'hex');
      
      return {
        valid: crypto.timingSafeEqual(expected, computed),
        algorithm: 'scrypt',
        timing_safe: true,
        config: config
      };
      
    } catch (error) {
      return {
        valid: false,
        error: error.message,
        algorithm: 'scrypt',
        timing_safe: true
      };
    }
  }

  // Calcul usage mémoire
  calculateMemoryUsage(params) {
    const memoryBytes = 128 * params.N * params.r;
    const memoryMB = memoryBytes / (1024 * 1024);
    
    return {
      bytes: memoryBytes,
      mb: Math.round(memoryMB),
      formula: `128 × ${params.N} × ${params.r} = ${memoryBytes} bytes`
    };
  }

  // Benchmark pour optimiser paramètres
  async benchmark(password = 'testpassword123', configs = ['interactive', 'server']) {
    const results = {};
    
    for (const configName of configs) {
      const startTime = Date.now();
      
      try {
        const result = await this.hashPassword(password, null, configName);
        const endTime = Date.now();
        const totalTime = endTime - startTime;
        
        results[configName] = {
          ...result,
          total_duration: `${totalTime}ms`,
          recommendation: this.getPerformanceRecommendation(totalTime)
        };
        
      } catch (error) {
        results[configName] = { 
          error: error.message,
          config: configName 
        };
      }
    }
    
    return results;
  }

  getPerformanceRecommendation(duration) {
    if (duration < 100) return '⚠️  Trop rapide - augmenter N';
    if (duration < 300) return '✅ Optimal pour web interactif';
    if (duration < 800) return '✅ Bon pour services backend';
    if (duration < 2000) return '🔒 Haute sécurité acceptable';
    return '🔒 Très sécurisé - vérifier ressources serveur';
  }

  // Configuration adaptative selon ressources système
  getConfigForResources(availableRAM_MB, targetTime_ms = 300) {
    // Calcul N optimal selon RAM disponible
    let N = 16384; // Base
    const r = 8;
    
    while ((128 * N * r) / (1024 * 1024) < availableRAM_MB * 0.1 && N < 1048576) {
      N *= 2;
    }
    
    return {
      N: N,
      r: r,
      p: 1,
      keylen: 64,
      estimated_memory_mb: Math.round((128 * N * r) / (1024 * 1024)),
      estimated_time: 'Variable selon CPU'
    };
  }
}

// Usage Production
const scryptManager = new ScryptManager();

// Hash sécurisé
(async () => {
  const password = 'MonMotDePasseSecurise2024!';
  
  // Hash avec configuration serveur
  const hashResult = await scryptManager.hashPassword(password, null, 'server');
  console.log('Hash Result:', hashResult);
  
  // Vérification
  const verification = await scryptManager.verifyPassword(
    password, 
    hashResult.hash, 
    hashResult.salt, 
    'server'
  );
  console.log('Verification:', verification);
  
  // Benchmark performance
  const benchmark = await scryptManager.benchmark();
  console.log('Benchmark:', benchmark);
  
  // Configuration adaptative
  const adaptiveConfig = scryptManager.getConfigForResources(4096); // 4GB RAM
  console.log('Adaptive Config:', adaptiveConfig);
})();

Python - Configuration Multi-Niveaux

import hashlib
import scrypt  # pip install scrypt
import secrets
import time
from typing import Dict, Optional, Tuple

class ScryptManager:
    """Manager scrypt optimisé pour production Python"""
    
    def __init__(self):
        # Configurations standard
        self.configs = {
            'interactive': {
                'N': 2**14,     # 16384
                'r': 8,
                'p': 1,
                'keylen': 64,
                'memory_mb': 128,
                'target_time': 200
            },
            'server': {
                'N': 2**15,     # 32768
                'r': 8,
                'p': 1,
                'keylen': 64,
                'memory_mb': 256,
                'target_time': 500
            },
            'high_security': {
                'N': 2**18,     # 262144
                'r': 8,
                'p': 1,
                'keylen': 64,
                'memory_mb': 2048,
                'target_time': 2000
            }
        }
    
    def hash_password(self, password: str, salt: bytes = None, config: str = 'server') -> Dict:
        """Hash avec scrypt memory-hard"""
        if salt is None:
            salt = secrets.token_bytes(32)
        
        params = self.configs[config]
        start_time = time.perf_counter()
        
        try:
            # Hash scrypt
            derived = scrypt.hash(
                password=password.encode('utf-8'),
                salt=salt,
                N=params['N'],
                r=params['r'],
                p=params['p'],
                buflen=params['keylen']
            )
            
            duration = (time.perf_counter() - start_time) * 1000
            
            return {
                'hash': derived.hex(),
                'salt': salt.hex(),
                'algorithm': 'scrypt',
                'params': {
                    'N': params['N'],
                    'r': params['r'],
                    'p': params['p'],
                    'keylen': params['keylen']
                },
                'config': config,
                'duration_ms': round(duration),
                'memory_usage': self._calculate_memory_usage(params),
                'timestamp': time.time()
            }
            
        except Exception as e:
            raise Exception(f"scrypt hashing failed: {e}")
    
    def verify_password(self, password: str, hash_hex: str, salt_hex: str, config: str = 'server') -> Dict:
        """Vérification sécurisée temps constant"""
        start_time = time.perf_counter()
        
        try:
            # Reconstruction du hash
            salt = bytes.fromhex(salt_hex)
            result = self.hash_password(password, salt, config)
            
            # Comparaison sécurisée
            expected = bytes.fromhex(hash_hex)
            computed = bytes.fromhex(result['hash'])
            
            is_valid = secrets.compare_digest(expected, computed)
            duration = (time.perf_counter() - start_time) * 1000
            
            return {
                'valid': is_valid,
                'algorithm': 'scrypt',
                'config': config,
                'duration_ms': round(duration),
                'timing_safe': True
            }
            
        except Exception:
            # Maintenir temps constant même en cas d'erreur
            time.sleep(0.1)
            return {
                'valid': False,
                'algorithm': 'scrypt',
                'timing_safe': True,
                'error': 'Verification failed'
            }
    
    def benchmark_configs(self, test_password: str = 'benchmark123') -> Dict:
        """Benchmark des configurations disponibles"""
        results = {}
        
        for config_name in self.configs.keys():
            try:
                start_time = time.perf_counter()
                result = self.hash_password(test_password, config=config_name)
                total_time = (time.perf_counter() - start_time) * 1000
                
                results[config_name] = {
                    'duration_ms': round(total_time),
                    'memory_mb': result['memory_usage']['mb'],
                    'params': result['params'],
                    'recommendation': self._get_recommendation(total_time),
                    'memory_hard_score': self._calculate_memory_hard_score(result['params'])
                }
                
            except Exception as e:
                results[config_name] = {'error': str(e)}
        
        return results
    
    def _calculate_memory_usage(self, params: Dict) -> Dict:
        """Calcul précis usage mémoire scrypt"""
        # Formule scrypt: 128 * N * r bytes
        memory_bytes = 128 * params['N'] * params['r']
        memory_mb = memory_bytes / (1024 * 1024)
        
        return {
            'bytes': memory_bytes,
            'mb': round(memory_mb),
            'formula': f"128 × {params['N']} × {params['r']} = {memory_bytes:,} bytes"
        }
    
    def _calculate_memory_hard_score(self, params: Dict) -> str:
        """Score résistance matériel spécialisé"""
        memory_mb = (128 * params['N'] * params['r']) / (1024 * 1024)
        
        if memory_mb >= 1024:
            return "EXCELLENT - Résistance ASIC maximale"
        elif memory_mb >= 512:
            return "TRÈS BON - Résistance GPU/ASIC élevée"
        elif memory_mb >= 128:
            return "BON - Résistance GPU correcte"
        else:
            return "INSUFFISANT - Augmenter paramètre N"
    
    def _get_recommendation(self, duration_ms: float) -> str:
        """Recommandations basées sur performance"""
        if duration_ms < 50:
            return "⚠️  Très rapide - paramètres faibles"
        elif duration_ms < 200:
            return "✅ Optimal pour applications interactives"
        elif duration_ms < 600:
            return "✅ Bon pour services backend"
        elif duration_ms < 1500:
            return "🔒 Haute sécurité - acceptable"
        else:
            return "🔒 Très sécurisé - impact performance significatif"
    
    def estimate_config_for_target(self, target_time_ms: int, max_memory_mb: int) -> Dict:
        """Estimation configuration pour temps et mémoire cibles"""
        # Partir d'une base et ajuster
        N = 16384  # Base 2^14
        r = 8
        p = 1
        
        # Ajuster N selon contraintes mémoire
        while (128 * N * r) / (1024 * 1024) <= max_memory_mb and N < 2**20:
            N *= 2
        
        # Si on a dépassé la limite mémoire, revenir en arrière
        if (128 * N * r) / (1024 * 1024) > max_memory_mb:
            N //= 2
        
        estimated_memory = (128 * N * r) / (1024 * 1024)
        
        return {
            'N': N,
            'r': r,
            'p': p,
            'keylen': 64,
            'estimated_memory_mb': round(estimated_memory),
            'max_memory_mb': max_memory_mb,
            'target_time_ms': target_time_ms,
            'note': 'Temps réel peut varier selon CPU'
        }

# Usage Production
if __name__ == "__main__":
    manager = ScryptManager()
    
    # Test complet
    password = "MotDePasseSecurise2024!"
    
    # Hash
    hash_result = manager.hash_password(password, config='server')
    print(f"Hash Result: {hash_result}")
    
    # Vérification
    verify_result = manager.verify_password(
        password, 
        hash_result['hash'], 
        hash_result['salt'], 
        'server'
    )
    print(f"Verification: {verify_result}")
    
    # Benchmark
    benchmark = manager.benchmark_configs()
    print("\nBenchmark Results:")
    for config, result in benchmark.items():
        print(f"  {config}: {result}")
    
    # Configuration optimisée
    optimal = manager.estimate_config_for_target(300, 512)  # 300ms, 512MB max
    print(f"\nOptimal Config: {optimal}")

Simulation Mining Crypto-monnaie

// scrypt pour Crypto-monnaies - Mining Configuration
// Inspiré de Litecoin et autres altcoins scrypt-based

class CryptocurrencyScryptMiner {
  constructor(options = {}) {
    // Configuration Litecoin-style (historique)
    this.litecoinConfig = {
      N: 1024,        // 2^10 (LTC original)
      r: 1,           // Block size factor réduit
      p: 1,           // Pas de parallélisme
      keylen: 32,     // 256-bit output
      target: 'Fast mining avec résistance ASIC'
    };
    
    // Configuration moderne haute sécurité
    this.modernConfig = {
      N: 32768,       // 2^15
      r: 8,           // Standard
      p: 1,
      keylen: 32,
      target: 'Maximum ASIC resistance'
    };
    
    this.config = options.mode === 'litecoin' ? this.litecoinConfig : this.modernConfig;
    this.difficulty = options.difficulty || 1;
  }

  // Hash de bloc crypto-monnaie
  async hashBlock(blockHeader, nonce = 0) {
    const input = blockHeader + nonce.toString(16).padStart(8, '0');
    
    return new Promise((resolve, reject) => {
      const startTime = Date.now();
      
      crypto.scrypt(input, 'salt', 32, {
        N: this.config.N,
        r: this.config.r,
        p: this.config.p
      }, (err, derivedKey) => {
        if (err) {
          reject(new Error(`Mining hash failed: ${err.message}`));
          return;
        }
        
        const hashTime = Date.now() - startTime;
        const hashHex = derivedKey.toString('hex');
        
        resolve({
          hash: hashHex,
          nonce: nonce,
          input: input,
          difficulty_met: this.checkDifficulty(hashHex),
          hash_time_ms: hashTime,
          hashrate_estimate: `${(1000/hashTime).toFixed(2)} H/s`,
          memory_usage_mb: Math.round((128 * this.config.N * this.config.r) / (1024 * 1024)),
          algorithm: 'scrypt'
        });
      });
    });
  }

  // Simulation mining avec proof-of-work
  async mineBlock(blockHeader, maxAttempts = 1000000) {
    console.log(`Starting mining with config: N=${this.config.N}, r=${this.config.r}`);
    console.log(`Target difficulty: ${this.difficulty} leading zeros`);
    
    const startTime = Date.now();
    let attempts = 0;
    
    for (let nonce = 0; nonce < maxAttempts; nonce++) {
      attempts++;
      
      try {
        const result = await this.hashBlock(blockHeader, nonce);
        
        if (result.difficulty_met) {
          const totalTime = Date.now() - startTime;
          
          return {
            success: true,
            block_hash: result.hash,
            winning_nonce: nonce,
            attempts: attempts,
            total_time_ms: totalTime,
            average_hashrate: `${(attempts / (totalTime / 1000)).toFixed(2)} H/s`,
            memory_requirement: result.memory_usage_mb + ' MB',
            asic_resistance: this.getAsicResistanceScore(),
            proof_of_work: {
              algorithm: 'scrypt',
              config: this.config,
              difficulty: this.difficulty,
              verified: true
            }
          };
        }
        
        // Progress reporting pour long mining
        if (attempts % 10000 === 0) {
          const currentTime = Date.now();
          const elapsed = (currentTime - startTime) / 1000;
          const hashrate = attempts / elapsed;
          console.log(`Progress: ${attempts} attempts, ${hashrate.toFixed(0)} H/s`);
        }
        
      } catch (error) {
        console.error(`Mining error at nonce ${nonce}: ${error.message}`);
        continue;
      }
    }
    
    // Échec mining dans la limite d'attempts
    return {
      success: false,
      attempts: attempts,
      total_time_ms: Date.now() - startTime,
      message: 'Max attempts reached without finding valid block',
      suggestion: 'Reduce difficulty or increase maxAttempts'
    };
  }

  // Vérification difficulté (leading zeros)
  checkDifficulty(hash) {
    const requiredZeros = '0'.repeat(this.difficulty);
    return hash.startsWith(requiredZeros);
  }

  // Score résistance ASIC
  getAsicResistanceScore() {
    const memoryMB = (128 * this.config.N * this.config.r) / (1024 * 1024);
    
    if (memoryMB >= 256) return 'EXCELLENT - ASIC mining uneconomical';
    if (memoryMB >= 128) return 'GOOD - ASIC resistance high';
    if (memoryMB >= 32) return 'MODERATE - Some ASIC resistance';
    return 'LOW - ASICs may be viable';
  }

  // Analyse économique mining
  calculateMiningEconomics(electricityCost_kWh = 0.10, hashrate_Hs = 1000, power_watts = 150) {
    const memoryMB = (128 * this.config.N * this.config.r) / (1024 * 1024);
    const timePerHash_s = 1 / hashrate_Hs;
    
    // Coût électrique par hash
    const powerCost_per_hour = (power_watts / 1000) * electricityCost_kWh;
    const powerCost_per_hash = (powerCost_per_hour / 3600) * timePerHash_s;
    
    return {
      memory_requirement_mb: memoryMB,
      time_per_hash_ms: timePerHash_s * 1000,
      power_cost_per_hash: powerCost_per_hash.toFixed(8) + ' $',
      daily_power_cost: (powerCost_per_hour * 24).toFixed(2) + ' $',
      asic_viability: memoryMB > 128 ? 'Uneconomical' : 'Possibly viable',
      gpu_efficiency: memoryMB < 512 ? 'Good' : 'Memory bound',
      recommendation: this.getMiningRecommendation(memoryMB, timePerHash_s)
    };
  }

  getMiningRecommendation(memoryMB, timePerHash) {
    if (memoryMB > 512) {
      return 'High memory config - Excellent ASIC resistance, suitable for fair mining';
    } else if (memoryMB > 128) {
      return 'Moderate memory - Good balance ASIC resistance and GPU efficiency';
    } else {
      return 'Low memory - Fast but lower ASIC resistance (legacy compatibility)';
    }
  }
}

// Usage Crypto Mining Simulation
const miner = new CryptocurrencyScryptMiner({ 
  mode: 'modern',  // or 'litecoin' for LTC-style
  difficulty: 4    // 4 leading zeros
});

// Simulation mining d'un bloc
(async () => {
  const blockHeader = 'Block#12345_timestamp_' + Date.now();
  
  console.log('Starting cryptocurrency mining simulation...');
  
  const result = await miner.mineBlock(blockHeader, 100000);
  console.log('Mining Result:', result);
  
  if (result.success) {
    // Analyse économique
    const economics = miner.calculateMiningEconomics(0.10, 500, 200);
    console.log('Mining Economics:', economics);
  }
})();

Actions Rapides

Métriques Memory-Hard

Création2009
Crypto adoption13 ans
Standard IETFRFC 7914
Résistance ASICProuvée
Mémoire (N=32k)256 MiB
Succès Prouvé

scrypt a démontré sa résistance ASIC avec 13 années de protection effective des réseaux crypto-monnaies.

Ressources et Documentation

RFC 7914
Standard IETF scrypt
Paper Original
Colin Percival (2009)
Litecoin
Première crypto-monnaie scrypt
Tarsnap
Service backup scrypt
GitHub Reference
Implémentation C référence
Node.js scrypt
Package Node.js

scrypt : Pionnier Memory-Hard et Résistance ASIC

scrypt a révolutionné la cryptographie en introduisant le concept memory-hard en 2009. Résistance ASIC démontrée par 13 années de protection des crypto-monnaies, standard IETF RFC 7914, et adoption continue pour applications nécessitant résistance maximale aux attaques matérielles spécialisées.

2009
Innovation memory-hard
13 ans
Crypto-monnaies
Memory-hard
ASIC resistant