//---------------------------------------------------------------------------- // EgalTech 2014-2026 //---------------------------------------------------------------------------- // File : KeyProc.cpp Data : 02.01.26 Versione : 3.1a1 // Contenuto : Funzioni per la gestione della chiave. // // // // Modifiche : 10.09.14 DS Creazione modulo. // 29.02.16 DS Controllo prodotti con & (and bit a bit). // 12.07.16 DS In recupero opzioni, se chiave ko azzero risultati. // 26.12.20 DS Gestione versione MMmm (vecchie chiavi convertite). // 24.01.24 DS Aggiunta GetKeyLevelEx con anche giorni scadenza assistenza. // 02.01.26 DS Aggiunta gestione versioni da 2801 a 36812. // //---------------------------------------------------------------------------- //------------------ Include ------------------------------------------------- #include "stdafx.h" #include #include "LockId.h" #include "Obfuscate.h" #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtBase64.h" #include "/EgtDev/Include/EgtCrc32.h" #include "/EgtDev/Include/SELkKeyProc.h" #include "/EgtDev/Include/SELkLockId.h" using namespace std ; //---------------------------------------------------------------------------- static const int MIN_DAYS = 20454 ; // giorni dal 01/01/1970 al 01/01/2026 static const int N_STEP = 7 ; //---------------------------------------------------------------------------- bool MakeKey( int nProd, int nVer, int nLev, int nExpDays, unsigned int nOpt1, unsigned int nOpt2, int nOptExpDays, const string& sScramKey, string& sKey) { // sistemazioni per nuova versione mensile valide fino alla 2712 // ( 16->16, 19->19, 21->21, 22->22, 2201->22, 2202->23 ... 2212->33, 2301->34, 2302->35 ... 2312->45, 2701->82 ... 2712->93) // nuove sistemazioni valide dalla 2801 alla 36812 (sempre NNN01 ... NNN12, dove NNN è la versione e il resto è il mese) int nVerNew = 0 ; int nVerTot = 0 ; int nVerA1 = -1 ; int nVerA2 = -1 ; if ( nVer >= 1 && nVer <= 22) { nVerNew = nVer ; nVerTot = nVerNew ; } else if ( nVer >= 2201 && nVer <= 2712) { int nVerY = nVer / 100 ; int nVerM = Clamp( nVer % 100 - 1, 0, 11) ; nVerNew = Clamp( 22 + 12 * ( nVerY - 22) + nVerM, 0, 99) ; nVerTot = nVerNew ; } else if ( nVer >= 2801 && nVer <= 36812) { int nVerY = nVer / 100 ; int nVerM = Clamp( nVer % 100 - 1, 0, 11) ; nVerNew = Clamp( 94 + nVerY % 6, 94, 99) ; nVerTot = Clamp( 12 * ( nVerY - 28) + nVerM, 0, 4095) ; nVerA1 = nVerTot / 64 ; nVerA2 = nVerTot % 64 ; } else return false ; // inizializzo parte pseudorandom srand( nVerTot + nLev) ; // preparo la stringa da criptare string sClearKey ; sClearKey += ToString( ( rand() % 9), 1) ; sClearKey += ToString( nProd, 4) ; sClearKey += ToString( nVerNew, 2) ; sClearKey += ToString( nLev, 2) ; sClearKey += ToString( ( rand() % 9), 1) ; sClearKey += ToString( nExpDays, 6) ; sClearKey += ToString( ( rand() % 9), 1) ; if ( nVerA1 >= 0) sClearKey[16] = nVerA1 + 63 ; sClearKey += " " ; sClearKey[17] = ( nOpt1 >> 0) & 0xFF ; sClearKey[18] = ( nOpt1 >> 8) & 0xFF ; sClearKey[19] = ( nOpt1 >> 16) & 0xFF ; sClearKey[20] = ( nOpt1 >> 24) & 0xFF ; sClearKey += " " ; sClearKey[21] = ( nOpt2 >> 0) & 0xFF ; sClearKey[22] = ( nOpt2 >> 8) & 0xFF ; sClearKey[23] = ( nOpt2 >> 16) & 0xFF ; sClearKey[24] = ( nOpt2 >> 24) & 0xFF ; sClearKey += ToString( ( rand() % 9), 1) ; if ( nVerA2 >= 0) sClearKey[25] = nVerA2 + 63 ; sClearKey += ToString( nOptExpDays, 6) ; // eseguo la cifratura string sMidKey = sClearKey ; if ( ! ScrambleData( sMidKey, sScramKey, N_STEP)) return false ; // aggiungo Crc32 AddCrc32ToString( sMidKey) ; // trasformo in Base64 return B64Encode( sMidKey, sKey) ; } //---------------------------------------------------------------------------- bool ReadKey( const string& sKey, const string& sScramKey, int& nProd, int& nVer, int& nLev, int& nExpDays, unsigned int& nOpt1, unsigned int& nOpt2, int& nOptExpDays) { // decodifico da Base64 string sClearKey ; if ( ! B64Decode( sKey, sClearKey)) return false ; // verifico e tolgo CRC32 if ( ! TestCrc32AndRemoveFromString( sClearKey)) return false ; // eseguo la decifratura if ( ! UnScrambleData( sClearKey, sScramKey, N_STEP)) return false ; // verifico la lunghezza della stringa risultante if ( sClearKey.length() != 32) return false ; // leggo le varie parti if ( ! FromString( sClearKey.substr( 1, 4), nProd)) return false ; if ( ! FromString( sClearKey.substr( 5, 2), nVer)) return false ; if ( ! FromString( sClearKey.substr( 7, 2), nLev)) return false ; if ( ! FromString( sClearKey.substr( 10, 6), nExpDays)) return false ; nOpt1 = ((unsigned char)sClearKey[17]) | ( ((unsigned char)sClearKey[18]) << 8) | ( ((unsigned char)sClearKey[19]) << 16) | ( ((unsigned char)sClearKey[20]) << 24) ; nOpt2 = ((unsigned char)sClearKey[21]) | ( ((unsigned char)sClearKey[22]) << 8) | ( ((unsigned char)sClearKey[23]) << 16) | ( ((unsigned char)sClearKey[24]) << 24) ; if ( ! FromString( sClearKey.substr( 26, 6), nOptExpDays)) return false ; // sistemazioni per nuova versione mensile valide fino alla 2712 // ( 16->16, 19->19, 21->21, 22->22, 2201->22, 2202->23 ... 2212->33, 2301->34, 2302->35 ... 2312->45, 2701->82 ... 2712->93) // nuove sistemazioni valide dalla 2801 alla 36812 (sempre NNN01 ... NNN12, dove NNN è la versione e il resto è il mese) if ( nVer > 93) { int nVerA1 = sClearKey[16] - 63 ; int nVerA2 = sClearKey[25] - 63 ; int nVerTot = nVerA1 * 64 + nVerA2 ; int nVerY = 28 + nVerTot / 12 ; int nVerM = nVerTot - ( 12 * ( nVerY - 28)) ; nVer = nVerY * 100 + nVerM + 1 ; } else if ( nVer > 22) { int nVerY = 22 + ( nVer - 22) / 12 ; int nVerM = nVer - ( 22 + 12 * ( nVerY - 22)) ; nVer = nVerY * 100 + nVerM + 1 ; } return true ; } //---------------------------------------------------------------------------- static int VerifyKey( const string& sKey, int nProd, int nVer, int nLev, int& nKProd, int& nKVer, int& nKLev, int& nKExpDays, unsigned int& nKOpt1, unsigned int& nKOpt2, int& nKOptExpDays) { // creo la chiave di scramble string sLockId2 ; if ( ! GetLockId2( sLockId2)) { if ( NotFoundNetHwKey()) return KEY_ERR_NETKEY_NOTFOUND ; else return KEY_ERR_MACHID ; } string sScramKey ; if ( ! ConvertLockId2ToScramKey( sLockId2, sScramKey)) return KEY_ERR_SCRAMKEY ; // recupero le informazioni nella chiave if ( ! ReadKey( sKey, sScramKey, nKProd, nKVer, nKLev, nKExpDays, nKOpt1, nKOpt2, nKOptExpDays)) return KEY_ERR_KEYDECODE ; // aggiusto i dati di versione (da 2712 si salta a 3101) if ( nVer < 100) nVer = nVer * 100 + 7 ; if ( nKVer < 100) nKVer = nKVer * 100 + 7 ; else if ( nKVer >= 2701 && nKVer <= 2712) nKVer += 300 ; // verifico dati prodotto if ( ( nProd & nKProd) != nProd) return KEY_ERR_PROD ; if ( nVer > nKVer + 100) return KEY_ERR_VER ; if ( nLev > nKLev) return KEY_ERR_LEV ; // verifico scadenza int nDays = GetCurrDay() ; if ( nDays < MIN_DAYS) return KEY_ERR_WRONG_TIME ; if ( nDays > nKExpDays) return KEY_ERR_TIME ; return KEY_OK ; } //---------------------------------------------------------------------------- int VerifyKey( const string& sKey, int nProd, int nVer, int nLev) { int nKProd, nKVer, nKLev, nKExpDays ; unsigned int nKOpt1, nKOpt2 ; int nKOptExpDays ; return VerifyKey( sKey, nProd, nVer, nLev, nKProd, nKVer, nKLev, nKExpDays, nKOpt1, nKOpt2, nKOptExpDays) ; } //---------------------------------------------------------------------------- int GetKeyLevel( const string& sKey, int nProd, int nVer, int nLev, int& nKLev, int& nKExpDays) { int nKProd, nKVer ; unsigned int nKOpt1, nKOpt2 ; int nKOptExpDays ; int nErr = VerifyKey( sKey, nProd, nVer, nLev, nKProd, nKVer, nKLev, nKExpDays, nKOpt1, nKOpt2, nKOptExpDays) ; if ( nErr != KEY_OK) { nKLev = 0 ; nKExpDays = 0 ; } return nErr ; } //---------------------------------------------------------------------------- int GetKeyLevelEx( const string& sKey, int nProd, int nVer, int nLev, int& nKLev, int& nKExpDays, int& nKAssExpDays) { int nKProd, nKVer ; unsigned int nKOpt1, nKOpt2 ; int nKOptExpDays ; int nErr = VerifyKey( sKey, nProd, nVer, nLev, nKProd, nKVer, nKLev, nKExpDays, nKOpt1, nKOpt2, nKOptExpDays) ; if ( nErr != KEY_OK) { nKLev = 0 ; nKExpDays = 0 ; nKAssExpDays = 0 ; } else { // sistemazioni per vecchie gestioni chiavi // 16xx -> 17xx, 18xx -> 18xx, 19xx -> 19xx, 21xx -> 20xx, 22xx -> 21xx, ... , 27xx -> 26xx, 31xx -> 27xx, ... int nKAssEnd = nKVer + ( nKVer < 1800 ? 100 : ( nKVer < 2000 ? 0 : ( nKVer < 3100 ? -100 : -400))) ; // si considera il primo giorno del mese successivo (mesi sono 0-based, con dicembre si va a gennaio anno dopo) int nKAssEndM = Clamp( nKAssEnd % 100, 1, 12) ; int nKAssEndY = nKAssEnd / 100 + 100 ; if ( nKAssEndM == 12) { nKAssEndM = 0 ; nKAssEndY += 1 ; } struct tm tmAssEnd = { 0, 0, 0, 1, nKAssEndM, nKAssEndY, 0, 0, 0} ; time_t nClock = mktime( &tmAssEnd) ; nKAssExpDays = int( nClock / ( 24 * 3600)) ; // (24*3600) secondi in un giorno nKAssExpDays = min( nKAssExpDays, nKExpDays) ; } return nErr ; } //---------------------------------------------------------------------------- int GetKeyOptions( const string& sKey, int nProd, int nVer, int nLev, unsigned int& nKOpt1, unsigned int& nKOpt2, int& nKOptExpDays) { int nKProd, nKVer, nKLev, nKExpDays ; int nErr = VerifyKey( sKey, nProd, nVer, nLev, nKProd, nKVer, nKLev, nKExpDays, nKOpt1, nKOpt2, nKOptExpDays) ; if ( nErr != KEY_OK) { nKOpt1 = 0 ; nKOpt2 = 0 ; nKOptExpDays = 0 ; } return nErr ; } //---------------------------------------------------------------------------- int GetCurrDay( void) { time_t nClock = time( nullptr) ; // secondi da 00:00:00 1/1/1970 in UTC long nDelta ; // offset tra UTC e tempo locale (nDelta = T_UTC - T_LOC) _tzset() ; if ( _get_timezone( &nDelta) != 0) // con errore nessun offset nDelta = 0 ; int nDays = int( ( nClock - nDelta) / ( 24 * 3600)) ; // (24*3600) secondi in un giorno return nDays ; } //---------------------------------------------------------------------------- int GetMinDay( void) { return MIN_DAYS ; }