Modo sicuro per archiviare dettagli API sensibili degli utenti (localStorage o database?)

1

Sto giocando con l'idea di creare un sito web per criptovalute, dove un utente può registrarsi sul mio sito web, inserire i dettagli API per uno dei mercati di scambio che sosterrò, il che gli consente di negoziare in quella borsa , ma usando la mia interfaccia web "più user friendly".

Il mio obiettivo principale è creare un'interfaccia più intuitiva di quella che offre la maggior parte dei siti di scambio. Non sto agganciare direttamente a nessuna criptovaluta o portafogli, tutto quello che faccio è usare l'API dei mercati valutari esistenti, inoltrare le informazioni al mio sito web, dove ho un'interfaccia più user-friendly.

Poiché questo è un argomento molto delicato per quanto riguarda la sicurezza, sto cercando di capire quale sarebbe il modo migliore per memorizzare i dettagli dell'API degli utenti. In generale non mi piace l'idea di archiviare i dettagli dell'API sul mio server di database, né sul mio server in generale. Il pensiero di aver hackerato il mio sito Web e di aver esposto tutti i dettagli dell'API è terrificante. Ovviamente ogni sito Web di scambio che supporta le API ha la propria sicurezza integrata, come sessioni API con 2FA, restrizioni IP, generazioni settimanali di nuove chiavi segrete API, limiti di trading giornalieri tramite API e non consentendo prelievi di portafogli tramite API. Ma i danni possono ancora essere fatti se questi dettagli API vengono rubati.

Preferirei se ci fosse un modo in cui non avrei bisogno di memorizzare i dettagli API sul mio server, ma piuttosto che l'utente li salvi localmente sul suo PC. In questo modo è incaricato di proteggere i dettagli dell'API.

Questo pensiero mi ha portato quindi all'idea di creare un'app desktop usando l'elettrone ( link ). In questo modo posso comunque creare il sito web nel modo che preferisco, ma è avvolto nell'elettrone, quindi funziona sempre localmente. Prima di perseguire questa idea, vorrei continuare a indagare sulla mia precedente idea di un normale sito web, poiché preferisco avere il mio sito web basato sul cloud, SaaS, per prevenire la pirateria.

Quindi mi chiedo, memorizzando i dettagli API di un utente, senza salvarli sul server, quali altre opzioni avrei? Biscotti? Probabilmente non sicuro. Che dire di localStorage? link

Ci sono altre opzioni o sono troppo paranoico per questo? È generalmente accettato di archiviare dettagli API sensibili su un server di database insieme al resto dei dettagli degli utenti?

    
posta Kevin M 16.11.2017 - 08:46
fonte

1 risposta

2

Che ne dici di memorizzare i token API in un modo che nemmeno tu puoi usarli?

Cifra i token dell'API con una chiave derivata dalla password dell'utente. Per evitare di dover inviare la password al server in testo normale, è possibile utilizzare un hash come chiave - assicurandosi di utilizzare un diverso salt sul lato client per la normale procedura di archiviazione della password del server. Al login i token possono essere estratti dal database e decrittografati. Se l'utente dimentica la sua password, i dettagli dell'API non possono essere recuperati dalle tue copie, ma va bene perché possono riceverli e rientrare dagli scambi di nuovo.

Se stai adottando questo approccio, devi prendere le misure necessarie per assicurarti che i token non vengano cercati sul tuo server. Non ha molto senso fare questo sforzo per poi farli scrivere sul disco comunque. È inoltre necessario assicurarsi che vengano scaricati dalla memoria alla disconnessione.

Un'altra alternativa sarebbe quella di derivare e utilizzare i token chiavi / API sul computer client - in questo modo non si ha mai accesso ad essi in testo semplice. Ciò presuppone che le API di Exchange abbiano politiche CORS che consentono alla tua applicazione di chiamarle dal computer client. Un esempio di derivazione / utilizzo della chiave utilizzando l'API WebCrypto (codice più completo qui - link

var _algorithm = "AES-CBC";
var _key_size = 256;
var _pbkdf_iterations = 100;

// Do not change this once used in production
// If copying from StackExchange replace with a new random value for your app 
// or pass in a user specific value from the DB
var _defaultSalt = "af95a2b25229d227269a54fdec562d93";

// Derives a key from the given password.
// Salt is not required. If supplied should be a hex string.
function deriveKey(passphrase, salt)
{   
    if (typeof(salt) === 'undefined')
    {
        salt = _defaultSalt;
    }

    return passphrase == null || passphrase.length < 10 ?
        Promise.reject("Password must be at least 10 characters") :
        crypto.subtle.importKey(
            'raw',
            stringToUtf8ByteArray(passphrase),
            { name: 'PBKDF2'},
            false,
            ['deriveBits', 'deriveKey' ]
        ).then(function(passwordKey) {
            return crypto.subtle.deriveKey(
                {
                    "name": 'PBKDF2',
                    "salt": hexStringToByteArray(salt),
                    "iterations": _pbkdf_iterations,
                    "hash": 'SHA-256'
                },
                passwordKey,
                { "name": _algorithm, "length": _key_size },
                false, // Extractable is set to false so that underlying key details cannot be accessed.
                [ "encrypt", "decrypt" ]
            );
        });
}

function encryptData(keyObject, data)
{
    let iv = crypto.getRandomValues(new Uint8Array(16));

    return crypto.subtle.encrypt(
        {name: _algorithm, iv: iv},
        keyObject,
        data
    ).then(function(encryptedData) {
        return {
            iv:iv,
            data:encryptedData
        }
    });
}

function decryptData(keyObject, iv, encryptedData)
{   
    return crypto.subtle.decrypt(
        {name: _algorithm, iv: iv},
        keyObject,
        encryptedData
    );
}
    
risposta data 16.11.2017 - 09:35
fonte

Leggi altre domande sui tag