Sto lavorando per ottenere una compilazione pulita con -Wsign-conversion
per il codice della libreria esistente. La biblioteca ha 25 anni o giù di lì. Alla fine, questa barra più alta sarà un varco di sicurezza e tutti i check-in dovranno essere soddisfatti o rifiutati.
Il codice della libreria esistente fa una discreta quantità di quanto segue (una semplificazione grossolana che cattura l'essenza):
class SHA1 : <inherited interfaces (contracts) and classes (behaviors)>
{
...
enum {DIGEST_SIZE = 20U};
unsigned int MaxDigestSize() { return DIGEST_SIZE; }
...
int m_digestSize;
}
Quindi, la libreria fa cose come (l'interazione è più complessa, ma questa cattura l'essenza):
if(m_digestSize == -1)
m_digestSize = MaxDiegstSize();
I chiamanti esterni possono usarlo come:
SHA1 sha;
...
// Calculate truncated digest
sha.Final(buffer, 8 /*signed or unsigned*/);
// Calculate using full digest
sha.Final(buffer, -1 /*signed*/);
// Calculate using full digest
sha.Final(buffer, sha.MaxDigestSize() /*unsigned*/);
Il motivo per cui -1
è popolare è il seguente "funziona" (si noti il passaggio da SHA-1
a SHA-512
):
SHA512 sha;
// Calculate using full digest
sha.Final(buffer, -1 /*signed*/);
Per la libreria, vogliamo convertire in unsigned
types per schiacciare l'avviso. Quindi, imposta un enum {DEFAULT_DIGEST_VALUE=...};
per gestire il caso di "default digest" che era compatibile con il "modello -1" esistente. Infine, rimuovi i confronti in -1
e utilizza un confronto con DEFAULT_DIGEST_VALUE
.
Ma enum {DEFAULT_DIGEST_VALUE=std::numeric_limits<unsigned int>::max()};
si è rivelato un vicolo cieco a causa di limitazioni in numeric_limits
.
Qualcuno ha suggerito di usare UINT_MAX
, ma non sono sicuro se dovrei usarlo (OS X non ha <cstdint>
, quindi introduce una dipendenza dell'intestazione C). Altri potenziali candidati sono __INT_MAX__ * 2U + 1
(da <limits>
su OS X) e ~(0)
(popolare in molti codici libreria, ma forse non corretto). In effetti, non sono sicuro che questo sia il percorso corretto in generale.
Qual è il modo corretto o migliore per:
- passa a unsigned per coerenza ed eventuale gate di sicurezza
- gestisci il "modello -1" per i chiamanti esistenti, non librerie
- fornire una soluzione portatile, in C ++
- risolve i potenziali problemi con i pattern di bit
Le mie scuse per aver posto una semplice domanda. Sono un architetto della sicurezza per mestiere. Ho bisogno dell'aiuto degli architetti del software perché non ho esperienza di ingegneria del software.
Dai commenti, ecco alcune ulteriori informazioni sui vincoli:
Codice esistente : la libreria esiste già e si chiama Crypto ++ . È stato creato negli anni '90 e gode di uno sviluppo continuo. È multipiattaforma e funziona su BSD, Linux, OS X, Solaris, Windows. La soluzione deve supportare standard più vecchi come C ++ 98 e C ++ 03. Possiamo abbandonare il supporto per C ++ 98 se la comunità è d'accordo.
Modifiche ABI - possiamo modificare l'API se la comunità è d'accordo. Sono abbastanza certo che ciò accadrà quando modificheremo la politica di una "compilazione pulita come porta di sicurezza". Non è necessario avere una compatibilità al 100%, ma dobbiamo gestire un codice base esistente di utenti che utilizzano -1
nel campo. Possiamo anche dare agli utenti l'avviso di modificare il loro codice con la macro del preprocessore CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
. Ma alla fine, le cose devono "funzionare" per loro.