2012-02-28 10 views
15

、コマンド:鍵機能へのパスワードはOpenSSLコマンドと互換性がありますか?例えば

そのキーが生成されますどのように
key = 33D890D33F91D52FC9B405A0DDA65336C3C4B557A3D79FE69AB674BE82C5C3D2 
iv = 677C95C475C0E057B739750748608A49 

:よう

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

出力何か? (答えとしてCコードが尋ねるにはあまりにも素晴らしいだろう:)) また、どのように生成されますか?

私にはある種のヘックスのように見えます。

答えて

30

OpenSSLは、機能EVP_BytesToKeyを使用します。 apps/enc.cに電話があります。 -md引数で別のダイジェストを指定しなかった場合、encユーティリティはキー導出アルゴリズム(KDF)でデフォルトでMD5ダイジェストを使用していました。現在は、デフォルトでSHA-256を使用しています。ここではMD5を使用した作業例です:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <openssl/evp.h> 

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; i<cipher->key_len; ++i) { printf("%02x", key[i]); } printf("\n"); 
    printf("IV: "); for(i=0; i<cipher->iv_len; ++i) { printf("%02x", iv[i]); } printf("\n"); 

    return 0; 
} 

使用例:

このOpenSSLのコマンドラインと同じキーを生成
gcc b2k.c -o b2k -lcrypto -g 
./b2k 
Key: 5f4dcc3b5aa765d61d8327deb882cf992b95990a9151374abd8ff8c5a7a0fe08 
IV: b7b4372cdfbcb3d16a2631b59b509e94 

いくつかの内部で使用される
openssl enc -aes-256-cbc -k password -nosalt -p < /dev/null 
key=5F4DCC3B5AA765D61D8327DEB882CF992B95990A9151374ABD8FF8C5A7A0FE08 
iv =B7B4372CDFBCB3D16A2631B59B509E94 

OpenSSL 1.1.0c changed the digest algorithmコンポーネント。以前はMD5が使用され、1.1.0はSHA256に切り替えられました。変更がEVP_BytesToKeyと、openssl encのようなコマンドの両方に影響しないように注意してください。誰もがSWIFT で同じことを実現するために探している場合

+0

恐ろしいポッサム! – Tudorizer

+1

これは私の人生を救った。私はopensslの鍵を得ることができず、パスフレーズと塩(iosで)を使ってivを得ました。私のプロジェクトにopensslライブラリを埋め込んだ後、私はこれを使用することができました。 –

+0

crypto ++にこの関数などの実装がありますか? – goji

1

は私はハッシュのためCryptoSwiftを使用し、迅速

/* 
- parameter keyLen: keyLen 
- parameter ivLen: ivLen 
- parameter digest: digest e.g "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<UInt8>(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 

} 

EVP_BytesToKeyを変換します。テストと作業 - ここmbedTLS /ポーラーSSLのバージョンがある3

+0

*「リンゴはiOSでOpenSSLを推奨していないので、これははるかにクリーンな方法です」* * - OpenSSLが更新されました。 iOSは放棄されます。長期的には、アップルに依存しないでください。 – jww

+0

リンゴが「おすすめしない」と言うと、私の経験から@jwwを真剣に受けなければなりません。私はあなたの言うことに同意しますが、私のアプリケーションが拒否されることはありません。私は多くのpplがまだiOSでOpenSSLを使用していることを知っています(私もそうしました)。私は本当に脅かされているのですか?Appleが取る決定は何ですか? – spaceMonkey

+0

このSwiftバージョンは実際に動作しますか?あなたは "addmd"変数を使用せず、最初のループの後の最後のダイジェストのフィードバックを省略しています。 – PatchyFog

0

スウィフト: これは、iOSで

UPDATEをOpenSSLを推奨していませんりんご同じくらいきれいな方法です。


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 (e.g. 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; 
} 
0

ここを通過し、誰もがハスケルでの作業、パフォーマンスのリファレンス実装を探している場合は、ここにある:

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) 

それはcryptoniteパッケージで提供されるハッシュアルゴリズムを使用しています。引数は、望ましいキーとIVサイズ(バイト数)、使用するハッシュアルゴリズム(例えば(undefined :: MD5)など)、オプションのsaltとパスワードです。結果はキーとIVのタプルです。

関連する問題