2009-04-17 6 views
2

は、 openssl -des3 encコマンドを使用して暗号化されたファイルを解読する手段です。 opensslはどのようにパスワードと塩を使ってキーを作るのですか?openssl des3 javaで解読する

答えて

5

OpenSSLのencユーティリティは、非標準(および低品質)のキー導出アルゴリズムをパスワードに使用します。次のコードは、encユーティリティがsaltとパスワードを指定してキーと初期化ベクトルを生成する方法を示しています。 encは、-saltオプションが指定されている場合(セキュリティにとって重大な場合)、暗号化されたファイルに "salt"値を格納することに注意してください。

public InputStream decrypt(InputStream is, byte[] password) 
    throws GeneralSecurityException, IOException 
{ 
    /* Parse the "salt" value from the stream. */ 
    byte[] header = new byte[16]; 
    for (int idx = 0; idx < header.length;) { 
    int n = is.read(header, idx, header.length - idx); 
    if (n < 0) 
     throw new EOFException("File header truncated."); 
    idx += n; 
    } 
    String magic = new String(header, 0, 8, "US-ASCII"); 
    if (!"Salted__".equals(magic)) 
    throw new IOException("Expected salt in header."); 

    /* Compute the key and IV with OpenSSL's non-standard method. */ 
    SecretKey secret; 
    IvParameterSpec iv; 
    byte[] digest = new byte[32]; 
    try { 
    MessageDigest md5 = MessageDigest.getInstance("MD5"); 
    md5.update(password); 
    md5.update(header, 8, 8); 
    md5.digest(digest, 0, 16); 
    md5.update(digest, 0, 16); 
    md5.update(password); 
    md5.update(header, 8, 8); 
    md5.digest(digest, 16, 16); 
    iv = new IvParameterSpec(digest, 24, 8); 
    DESedeKeySpec keySpec = new DESedeKeySpec(digest); 
    SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede"); 
    secret = factory.generateSecret(keySpec); 
    } 
    finally { 
    Arrays.fill(digest, (byte) 0); 
    } 

    /* Initialize the cipher. */ 
    Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
    cipher.init(Cipher.DECRYPT_MODE, secret, iv); 
    return new CipherInputStream(is, cipher); 
} 

このキーとIV生成はencコマンドは反復countとして1を使用しています(悪い考えで、encの私のバージョンのmanページにバグとして注目さ)EVP_BytesToKey(3) documentation.に記載されており、 MD5をダイジェストアルゴリズム—として「壊れた」アルゴリズムとする。

OpenSSLがテキストパスワードをバイトに変換する方法は明確ではありません。私はそれがデフォルトのプラットフォーム文字エンコーディングを使用していると推測しています。したがって、Stringパスワードがついていない場合(「ゼロ化」できないため)、password.getBytes()に電話してbyte[]に変換してください。

可能であれば、Java 6のConsoleまたはSwingのJPasswordFieldのようなものを使用してパスワードを取得してください。これらは配列を返すので、パスワードをメモリから削除することができます。Arrays.fill(password, '\0');

1

ありがとう、あなたのポストはEricksonです。それはキーとIVのルーチンへのopensslのパスワードを作り直すのに大いに役立った。

私は少し違っていました。恐らくDESよりむしろ、ブタの暗号化されたデータを解読する必要があるからです。下記参照。

また、私は、opensslがバイト00、0a、または0dに遭遇したときにパスワードの読み取りを停止することを発見しました。一般的に私はopensslはバイト11と127の間のパスワード文字だけを読み込むと思います。したがって、以下の例では、00、0aまたは0dが含まれている場合にパスワードを切り捨てるコードがあります。

 /* Compute the key and IV with OpenSSL's non-standard method. */ 
    final byte[] digest = new byte[32]; 
    final MessageDigest md5 = MessageDigest.getInstance("MD5"); 
    md5.update(password, 0); 
    // append the salt 
    md5.update(salt); 
    // run the digest and output 16 bytes to the first 16 bytes to the digest array. Digest is reset 
    md5.digest(digest, 0, 16); 
    // write the first 16 bytes from the digest array back to the buffer 
    md5.update(digest, 0, 16); 
    // append the password 
    md5.update(password, 0); 
    // append the salt 
    md5.update(salt); 
    // run the digest and output 16 bytes to the last 16 bytes of the digest array 
    md5.digest(digest, 16, 16); 
    key = Arrays.copyOfRange(digest, 0, 16); 
    iv = Arrays.copyOfRange(digest, 16, 24); 

上述このコードはorg.bouncycastle.crypto.generators.OpenSSLPBEParametersGeneratorを使用して3行で置き換えることができます。それは

final OpenSSLPBEParametersGenerator generator = new OpenSSLPBEParametersGenerator(); 
generator.init(password, salt); 
final ParametersWithIV ivParam = (ParametersWithIV)generator.generateDerivedParameters(16, 8); 
final KeyParameter keyParameter = (KeyParameter)ivParam.getParameters(); 
関連する問題