Codice promozionale basato sul valore numerico

5

Ho un campo id utente che ha un valore compreso tra 10000 e 999999. Voglio creare un codice promozionale basato su questo campo.

Il codice promozionale verrà utilizzato dagli utenti per segnalare i nuovi utenti.

Le caratteristiche del codice promozionale:

  • nessun campo aggiuntivo nel database - tramite algoritmo il codice promozionale può essere decodificato di nuovo a userid
  • difficile indovinare l'ID utente
  • facile da condividere verbalmente

Puoi suggerire alcune idee o esempi su come affrontare questo problema?

    
posta GeorgiY 18.04.2018 - 12:19
fonte

3 risposte

3

no additional field in the database - through algorithm the promotional code can be decoded back to userid

Mentre di solito questo sarebbe risolto attraverso una tabella aggiuntiva con riferimenti incrociati, idealmente 1: n, in modo che un ID utente possa avere più codici promozionali validi, questo sembra essere esplicitamente fuori portata. Questo preclude anche i promocodes auto-scelti, sfortunatamente.

hard to guess the userid

Idealmente, non dovrebbe essere possibile indovinare l'id utente (e assicurarsi di aver indovinato giusto).

easy to share verbally

Questo potrebbe essere il problema più grande se non si utilizza una tabella aggiuntiva.

Propongo la seguente soluzione:

Cripta i tuoi ID utente.

Esistono diversi schemi di crittografia che possono produrre risultati più piccoli che possono essere utilizzati. Ma se, come suggerito dalla tua restrizione sulle modifiche al database, il costo di implementazione è un fattore trainante, l'RSA raw potrebbe valere la pena dare un'occhiata perché mantiene il testo cifrato relativamente piccolo e le librerie di crittografia sono prontamente disponibili.

I bit risultanti potrebbero essere tradotti in parole in linguaggio naturale, ad esempio utilizzando un vocabolario per diceware .

Utilizzando questo approccio, il testo cifrato sarebbe facile da comunicare (dato che si tratta di una stringa di parole) e facile da decifrare (traduzione inversa, decifrare i bit risultanti).

C'è comunque un problema: quei codici potrebbero richiedere più tempo del previsto (a seconda dello schema di crittografia scelto) e potrebbero comportare una penalità temporale quando si tratta di digitarli.

Sebbene questo produca codici più lunghi (in termini di dimensioni delle stringhe), è molto più facile da trasmettere verbalmente, specialmente per i madrelingua, rispetto al risultato di base32, base64 o uno dei soliti approcci per la codifica del trasporto.

Quindi, anche se una tabella 1: n sarebbe l'ideale, usare uno schema di crittografia appropriato e finire con un codice di 3 parole potrebbe essere la cosa migliore - e sicuramente più facile da condividere verbalmente rispetto ai soliti sospetti per i dati di codifica .

    
risposta data 18.04.2018 - 13:10
fonte
2

Consiglierei il seguente approccio:

  • Cripta l'userid con un algoritmo che produce piccoli output, ad es. ha una piccola dimensione del blocco. Un alterante sarebbe cifrario Hasty Pudding che dice una dimensione di blocco di 32 bit.
  • Codifica l'output con base32 . Ottieni quindi un codice promozionale lungo sette lettere.
  • Per ottenere un ID utente da un codice promozionale, basta invertire la procedura: decodifica e decrittografia.

Devo ammettere che non sono sicuro di come le dimensioni ridotte dei blocchi influenzino la sicurezza del codice nel tuo caso d'uso. Quindi, prima di dichiarare questa prova dell'acqua, potresti volerlo esaminare.

Si noti che questo sarebbe molto facile da fare in modo sicuro semplicemente usando una tabella di traduzione, mettendo in relazione i codici promozionali casuali con gli utenti. Tuttavia, ciò violerebbe il tuo requisito che nessuna modifica del database dovrebbe essere necessaria.

    
risposta data 18.04.2018 - 13:20
fonte
1

Mantenere l'ID utente nascosto è facile. La difficoltà è prevenire le collisioni: la maggior parte delle funzioni di hash che sono così brevi da essere facilmente comunicate, o troncate a quella lunghezza, si scontreranno casualmente.

Lo stesso vale per le funzioni di crittografia: poiché la crittografia strong produce un testo cifrato casuale, produrrà collisioni a causa del paradosso del compleanno. Quindi ciò di cui hai bisogno è una trasformazione one-to-one.

Un approccio sta usando un PRNG con un periodo deterministico e sufficiente e solo il suo numero precedente come stato, come LFSR , con UserID come numero di round. Il rovescio della medaglia è che può essere lento se non scritto in un linguaggio veloce compilato.

Un modo più semplice è quello di crittografare il valore con un cifrario a blocchi molto breve. Skip32 può essere implementato senza quasi nessuno sforzo. Hasty Pudding è ancora più vicino, in quanto può essere impostato su un blocco a 20 bit.

Per la traduzione verbale, 20-21 bit si traducono in 7 numeri o cinque alfanumerici a 5 bit con 2-5 bit di riserva. I pezzi di ricambio sono necessari come cifra di controllo contro errori di battitura. Puoi utilizzare solo quei 2-5 bit se la tua base di utenti è piccola ora e aggiungi un'altra cifra di controllo mentre la tua base di utenti si avvicina a un milione.

Personalmente, preferisco un breve alfanumerico a una passphrase: questi ultimi creano la tentazione di affidarsi alla memoria, e la memoria umana spesso sostituisce le parole ai sinonimi. Codici e numeri sono più facili da scrivere e le persone di solito possono farlo. OTOH, una passphrase non richiede cifre di controllo, poiché il suo dizionario limitato è un controllo in sé. Si riduce al tuo caso d'uso e alle tue preferenze.

Tutti questi approcci sono insicuri; LFSR non è nemmeno un cifrario, gli altri due sono piuttosto deboli. Ma la tua sicurezza è limitata dalla breve durata del codice di invito e dalla necessità di evitare le collisioni garantite.

    
risposta data 18.04.2018 - 20:56
fonte

Leggi altre domande sui tag