#!/usr/bin/env node // Test de signature AWS pour DigitalOcean Spaces const crypto = require('crypto'); // Configuration avec ta clé read-only const config = { DO_ACCESS_KEY: 'DO801XTYPE968NZGAQM3', DO_SECRET_KEY: 'rfKPjampdpUCYhn02XrKg6IWKmqebjg9HQTGxNLzJQY', DO_REGION: 'fra1', DO_ENDPOINT: 'https://autocollant.fra1.digitaloceanspaces.com', DO_CONTENT_PATH: 'Class_generator/ContentMe' }; // Fonction de hash SHA256 function sha256(message) { return crypto.createHash('sha256').update(message, 'utf8').digest('hex'); } // Fonction HMAC SHA256 function hmacSha256(key, message) { return crypto.createHmac('sha256', key).update(message, 'utf8').digest(); } // Génération de la signature AWS V4 async function generateAWSSignature(method, url) { const accessKey = config.DO_ACCESS_KEY; const secretKey = config.DO_SECRET_KEY; const region = config.DO_REGION; const service = 's3'; const now = new Date(); const dateStamp = now.toISOString().slice(0, 10).replace(/-/g, ''); const timeStamp = now.toISOString().slice(0, 19).replace(/[-:]/g, '') + 'Z'; console.log(`🕐 Timestamp: ${timeStamp}`); console.log(`📅 Date: ${dateStamp}`); // Parse URL const urlObj = new URL(url); const host = urlObj.hostname; const canonicalUri = urlObj.pathname || '/'; const canonicalQueryString = urlObj.search ? urlObj.search.slice(1) : ''; console.log(`🌐 Host: ${host}`); console.log(`📍 URI: ${canonicalUri}`); console.log(`❓ Query: ${canonicalQueryString}`); // Canonical headers const canonicalHeaders = `host:${host}\nx-amz-date:${timeStamp}\n`; const signedHeaders = 'host;x-amz-date'; console.log(`📝 Canonical headers:\n${canonicalHeaders}`); // Create canonical request const payloadHash = method === 'GET' ? sha256('') : 'UNSIGNED-PAYLOAD'; const canonicalRequest = [ method, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders, payloadHash ].join('\n'); console.log(`📋 Canonical request:\n${canonicalRequest}`); console.log(`🔢 Payload hash: ${payloadHash}`); // Create string to sign const algorithm = 'AWS4-HMAC-SHA256'; const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`; const canonicalRequestHash = sha256(canonicalRequest); const stringToSign = [ algorithm, timeStamp, credentialScope, canonicalRequestHash ].join('\n'); console.log(`🔐 String to sign:\n${stringToSign}`); console.log(`🔗 Canonical request hash: ${canonicalRequestHash}`); // Calculate signature const kDate = hmacSha256('AWS4' + secretKey, dateStamp); const kRegion = hmacSha256(kDate, region); const kService = hmacSha256(kRegion, service); const kSigning = hmacSha256(kService, 'aws4_request'); const signature = hmacSha256(kSigning, stringToSign).toString('hex'); console.log(`✍️ Signature: ${signature}`); // Create authorization header const authorization = `${algorithm} Credential=${accessKey}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`; console.log(`🔑 Authorization: ${authorization}`); return { 'Authorization': authorization, 'X-Amz-Date': timeStamp, 'X-Amz-Content-Sha256': payloadHash }; } // Test avec fetch async function testDigitalOceanAccess() { console.log('🚀 Test d\'accès DigitalOcean Spaces avec signature AWS\n'); const testUrl = `${config.DO_ENDPOINT}/${config.DO_CONTENT_PATH}/greetings-basic.json`; console.log(`🎯 URL de test: ${testUrl}\n`); try { const headers = await generateAWSSignature('GET', testUrl); console.log('\n📦 Headers finaux:'); console.log(JSON.stringify(headers, null, 2)); // Test avec node-fetch si disponible try { const fetch = require('node-fetch'); console.log('\n🌐 Test avec node-fetch...'); const response = await fetch(testUrl, { method: 'GET', headers: headers }); console.log(`📡 Status: ${response.status} ${response.statusText}`); if (response.ok) { const content = await response.text(); console.log(`✅ Succès ! Contenu (${content.length} chars): ${content.substring(0, 200)}...`); } else { const errorText = await response.text(); console.log(`❌ Erreur: ${errorText}`); } } catch (fetchError) { console.log('⚠️ node-fetch non disponible, test signature seulement'); console.log('✅ Signature générée avec succès !'); } } catch (error) { console.error(`❌ Erreur: ${error.message}`); } } // Lancer le test testDigitalOceanAccess();