Пароль к ключевой функции, совместимой с командами OpenSSL?

Например, команда:

openssl enc -aes-256-cbc -a -in test.txt -k pinkrhino -nosalt -p -out openssl_output.txt 

выводит что-то вроде:

 key = 33D890D33F91D52FC9B405A0DDA65336C3C4B557A3D79FE69AB674BE82C5C3D2 iv = 677C95C475C0E057B739750748608A49 

Как генерируется этот ключ? (C-код как ответ был бы слишком потрясающим, чтобы спросить :)) Также, как генерируется iv?

Похож на какой-то гексагон для меня.

OpenSSL использует функцию EVP_BytesToKey . Вы можете найти его в apps/enc.c Утилита enc используемая для вычисления MD5 по умолчанию в алгоритме определения ключей (KDF), если вы не указали другой дайджест с аргументом -md . Теперь он использует SHA-256 по умолчанию. Вот пример использования MD5:

 #include  #include  #include  #include  int main(int argc, char *argv[]) { const EVP_CIPHER *cipher; const EVP_MD *dgst = NULL; unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; const char *password = "password"; const unsigned char *salt = NULL; int i; OpenSSL_add_all_algorithms(); cipher = EVP_get_cipherbyname("aes-256-cbc"); if(!cipher) { fprintf(stderr, "no such cipher\n"); return 1; } dgst=EVP_get_digestbyname("md5"); if(!dgst) { fprintf(stderr, "no such digest\n"); return 1; } if(!EVP_BytesToKey(cipher, dgst, salt, (unsigned char *) password, strlen(password), 1, key, iv)) { fprintf(stderr, "EVP_BytesToKey failed\n"); return 1; } printf("Key: "); for(i=0; ikey_len; ++i) { printf("%02x", key[i]); } printf("\n"); printf("IV: "); for(i=0; iiv_len; ++i) { printf("%02x", iv[i]); } printf("\n"); return 0; } 

Пример использования:

 gcc b2k.c -o b2k -lcrypto -g ./b2k Key: 5f4dcc3b5aa765d61d8327deb882cf992b95990a9151374abd8ff8c5a7a0fe08 IV: b7b4372cdfbcb3d16a2631b59b509e94 

Что генерирует тот же ключ, что и в командной строке OpenSSL:

 openssl enc -aes-256-cbc -k password -nosalt -p < /dev/null key=5F4DCC3B5AA765D61D8327DEB882CF992B95990A9151374ABD8FF8C5A7A0FE08 iv =B7B4372CDFBCB3D16A2631B59B509E94 

OpenSSL 1.1.0c изменил алгоритм дайджеста, используемый в некоторых внутренних компонентах. Раньше использовался MD5, а 1.1.0 - SHA256. Будьте осторожны, это изменение не влияет на вас как в EVP_BytesToKey и в командах вроде openssl enc .

Если кто-то ищет реализацию в SWIFT, я преобразовал EVP_BytesToKey в быстрый

  /* - parameter keyLen: keyLen - parameter ivLen: ivLen - parameter digest: digest eg "md5" or "sha1" - parameter salt: salt - parameter data: data - parameter count: count - returns: key and IV respectively */ open static func evpBytesToKey(_ keyLen:Int, ivLen:Int, digest:String, salt:[UInt8], data:Data, count:Int)-> [[UInt8]] { let saltData = Data(bytes: UnsafePointer(salt), count: Int(salt.count)) var both = [[UInt8]](repeating: [UInt8](), count: 2) var key = [UInt8](repeating: 0,count: keyLen) var key_ix = 0 var iv = [UInt8](repeating: 0,count: ivLen) var iv_ix = 0 var nkey = keyLen; var niv = ivLen; var i = 0 var addmd = 0 var md:Data = Data() var md_buf:[UInt8] while true { addmd = addmd + 1 md.append(data) md.append(saltData) if(digest=="md5"){ md = NSData(data:md.md5()) as Data }else if (digest == "sha1"){ md = NSData(data:md.sha1()) as Data } for _ in 1...(count-1){ if(digest=="md5"){ md = NSData(data:md.md5()) as Data }else if (digest == "sha1"){ md = NSData(data:md.sha1()) as Data } } md_buf = Array (UnsafeBufferPointer(start: md.bytes, count: md.count)) // md_buf = Array(UnsafeBufferPointer(start: md.bytes.bindMemory(to: UInt8.self, capacity: md.count), count: md.length)) i = 0 if (nkey > 0) { while(true) { if (nkey == 0){ break } if (i == md.count){ break } key[key_ix] = md_buf[i]; key_ix = key_ix + 1 nkey = nkey - 1 i = i + 1 } } if (niv > 0 && i != md_buf.count) { while(true) { if (niv == 0){ break } if (i == md_buf.count){ break } iv[iv_ix] = md_buf[i] iv_ix = iv_ix + 1 niv = niv - 1 i = i + 1 } } if (nkey == 0 && niv == 0) { break } } both[0] = key both[1] = iv return both } 

Я использую CryptoSwift для hashа. Это намного более чистый способ, поскольку яблоки не рекомендуют OpenSSL в iOS

ОБНОВЛЕНИЕ: Swift 3

Вот версия для mbedTLS / Polar SSL – протестирована и работает.

 typedef int bool; #define false 0 #define true (!false) //------------------------------------------------------------------------------ static bool EVP_BytesToKey( const unsigned int nDesiredKeyLen, const unsigned char* salt, const unsigned char* password, const unsigned int nPwdLen, unsigned char* pOutKey, unsigned char* pOutIV ) { // This is a re-implemntation of openssl's password to key & IV routine for mbedtls. // (See openssl apps/enc.c and /crypto/evp/evp_key.c) It is not any kind of // standard (eg PBKDF2), and it only uses an interation count of 1, so it's // pretty crappy. MD5 is used as the digest in Openssl 1.0.2, 1.1 and late // use SHA256. Since this is for embedded system, I figure you know what you've // got, so I made it compile-time configurable. // // The signature has been re-jiggered to make it less general. // // See: https://wiki.openssl.org/index.php/Manual:EVP_BytesToKey(3) // And: https://www.cryptopp.com/wiki/OPENSSL_EVP_BytesToKey #define IV_BYTE_COUNT 16 #if BTK_USE_MD5 # define DIGEST_BYTE_COUNT 16 // MD5 #else # define DIGEST_BYTE_COUNT 32 // SHA #endif bool bRet; unsigned char md_buf[ DIGEST_BYTE_COUNT ]; mbedtls_md_context_t md_ctx; bool bAddLastMD = false; unsigned int nKeyToGo = nDesiredKeyLen; // 32, typical unsigned int nIVToGo = IV_BYTE_COUNT; mbedtls_md_init( &md_ctx ); #if BTK_USE_MD5 int rc = mbedtls_md_setup( &md_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ), 0 ); #else int rc = mbedtls_md_setup( &md_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 ); #endif if (rc != 0 ) { fprintf( stderr, "mbedutils_md_setup() failed -0x%04x\n", -rc ); bRet = false; goto exit; } while( 1 ) { mbedtls_md_starts( &md_ctx ); // start digest if ( bAddLastMD == false ) // first time { bAddLastMD = true; // do it next time } else { mbedtls_md_update( &md_ctx, &md_buf[0], DIGEST_BYTE_COUNT ); } mbedtls_md_update( &md_ctx, &password[0], nPwdLen ); mbedtls_md_update( &md_ctx, &salt[0], 8 ); mbedtls_md_finish( &md_ctx, &md_buf[0] ); // // Iteration loop here in original removed as unused by "openssl enc" // // Following code treats the output key and iv as one long, concatentated buffer // and smears as much digest across it as is available. If not enough, it takes the // big, enclosing loop, makes more digest, and continues where it left off on // the last iteration. unsigned int ii = 0; // index into mb_buf if ( nKeyToGo != 0 ) // still have key to fill in? { while( 1 ) { if ( nKeyToGo == 0 ) // key part is full/done break; if ( ii == DIGEST_BYTE_COUNT ) // ran out of digest, so loop break; *pOutKey++ = md_buf[ ii ]; // stick byte in output key nKeyToGo--; ii++; } } if ( nIVToGo != 0 // still have fill up IV && // and ii != DIGEST_BYTE_COUNT // have some digest available ) { while( 1 ) { if ( nIVToGo == 0 ) // iv is full/done break; if ( ii == DIGEST_BYTE_COUNT ) // ran out of digest, so loop break; *pOutIV++ = md_buf[ ii ]; // stick byte in output IV nIVToGo--; ii++; } } if ( nKeyToGo == 0 && nIVToGo == 0 ) // output full, break main loop and exit break; } // outermost while loop bRet = true; exit: mbedtls_md_free( &md_ctx ); return bRet; } 

Если кто-то, проходящий здесь, ищет рабочую, исполнительную ссылку в Haskell, вот она:

 import Crypto.Hash import qualified Data.ByteString as B import Data.ByteArray (convert) import Data.Monoid ((<>)) evpBytesToKey :: HashAlgorithm alg => Int -> Int -> alg -> Maybe B.ByteString -> B.ByteString -> (B.ByteString, B.ByteString) evpBytesToKey keyLen ivLen alg mSalt password = let bytes = B.concat . take required . iterate go $ hash' passAndSalt (key, rest) = B.splitAt keyLen bytes in (key, B.take ivLen rest) where hash' = convert . hashWith alg required = 1 + ((keyLen + ivLen - 1) `div` hashDigestSize alg) passAndSalt = maybe password (password <>) mSalt go = hash' . (<> passAndSalt) 

Он использует hash-алгоритмы, предоставляемые пакетом криптонита . Аргументами являются желаемый ключ и размер IV в байтах, используемый hash-алгоритм (например, (undefined :: MD5) ), дополнительная соль и пароль. Результатом является кортеж ключа и IV.

  • Как зашифровать файл с SD-карты с помощью AES на Android?
  • JCE не может аутентифицировать поставщика BC в приложении java swing
  • Разница между кодированием и шифрованием
  • SQLite с защитой от шифрования / паролей
  • Как невозможно «расшифровать» hash MD5?
  • Шифрование / расшифровка classа NSData-AES в cocoa
  • Почему неправильный пароль приводит к тому, что «Заполнение недопустима и не может быть удалено»?
  • Преобразование изображения в base64
  • Какой «хороший» алгоритм шифрования блоков имеет самый короткий результат?
  • Определения Truststore и Keystore
  • Как использовать шифрование / дешифрование 3DES в Java?
  • Давайте будем гением компьютера.