0

古いコードとインターフェイスするには、Cで簡単なDES暗号化を行う必要があります。私が理解していることから、このために「crypt」ライブラリを使用できます。関数setkey、encrypt、cryptなどがあります。私はそれをいじっていて、正しく理解できません。setkey/encryptのmanページの例が欠けています。

いくつかのJavaコードで取得できるのと同じ出力を取得したいと思います(以下を参照)。

したがって、Cに2つの文字配列があるとしましょう。

char *message = "hellothe";
char *key = "iamakey0";

誰かがこれらをsetkey/encryptで暗号化して、Javaコードから得たのと同じ結果を得る方法の例を挙げてもらえますか?メッセージとキーを64バイトの配列に配置する必要があることを理解しています。各文字はビットを表しますが、その一部も混乱を招きます。どうやらあなたはそれについてもビットパリティを正しく取得する必要がありますか?

public static byte[] encryptDES(byte[] message, byte[] key) {
    byte[] encrypted = new byte[0];
    try{
        Cipher c = Cipher.getInstance("DES");
        c.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(key,"DES"));
        encrypted = c.doFinal(message);
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    return encrypted;
}
4

2 に答える 2

2

Cipher.getInstance文字列だけで呼び出しているため"DES"、暗号モードやパディング方法を指定していません。これは、デフォルトを取得することを意味します。これは、使用しているJava暗号化プロバイダーによって異なります。互換性のあるCを作成するには、デフォルトを正確に知る必要があります(デフォルトに依存するのではなく、実際に指定する必要があります)。

SunJCEプロバイダーを使用している場合、DESのデフォルトはECBモードとPKCS#5パディングです。これを行うための最良の方法は、おそらくOpenSSLまたは別の重要な暗号ライブラリを使用することです-しかし、UNIXタイプのプラットフォームの標準Cライブラリに通常見られる関数を使用したい場合は、ecb_crypt関数のファミリーがはるかに簡単になりますsetkey/encryptファミリーよりも一緒に仕事をする。

暗号化するときにPKCS#5パディングを追加し、復号化するときにチェック(および破棄)する必要があります)。次のecb_pkcs5_encrypt関数は、これらの関数を使用して、上記のJavaコードとほぼ同等の機能を実行する必要があります。

/* Returns a newly-allocated buffer containing the contents of `data',
 * padded out to a multiple of 8 bytes using PKCS #5 style padding.
 *
 * If `padded_len` is non-NULL, the value it points to is updated to
 * the size of the padded output data.
 *
 * Returns NULL on error.
 */
char *pad_pkcs5(const char *data, size_t data_len, size_t *padded_len)
{
    char *padded_data;
    unsigned padding_len = 8 - (data_len % 8);
    const char padding = padding_len;
    char *pad_ptr;

    /* check for length overflow */
    if (data_len + padding_len < data_len)
        return NULL;

    /* Copy data into a new buffer and pad it out */
    padded_data = malloc(data_len + padding_len);

    if (!padded_data)
        return NULL;

    memcpy(padded_data, data, data_len);

    if (*padded_len)
    {
        *padded_len = data_len + padding_len;
    }

    /* Add the padding bytes */
    pad_ptr = padded_data + data_len;
    while (padding_len--)
    {
        *pad_ptr++ = padding;
    }

    return padded_data;
}

/* Returns a newly-allocated buffer containing the contents of `data',
 * encrypted with `key' using DES/ECB/PKCS5.
 *
 * If `out_len` is non-NULL, the value it points to is updated to
 * the size of the encrypted output data (which will always be a
 * multiple of 8).
 *
 * Returns NULL on error.
 */
char *ecb_pkcs5_encrypt(const char *key, const char *data, size_t data_len, size_t *out_len)
{
    char des_key[8];
    char *padded_data;
    size_t padded_len;
    int status;

    /* One of the few cases where strncpy() is exactly what we want! */
    strncpy(des_key, key, sizeof des_key);
    des_setparity(des_key);

    padded_data = pad_pkcs5(data, data_len, &padded_len);

    if (!padded_data)
        return NULL;

    status = ecb_crypt(des_key, padded_data, padded_len, DES_ENCRYPT);

    if (DES_FAILED(status))
        return NULL;

    if (out_len)
        *out_len = padded_len;

    return padded_data;
}
于 2009-09-14T02:11:46.853 に答える
1

crypt()は使用しないでください。非標準のアルゴリズムを使用しているため、他のシステムとの相互運用は非常に困難です。その上、DESはとにかく安全ではありません。

CでOpenSSLを使用することをお勧めします。その暗号のほとんどはJCEと互換性があります。

本当にcryptを使用する必要がある場合、SunのJREにはcryptを処理するクラスが付属しています。

   com.sun.security.auth.module.Crypt

これは内部クラスであるため、ドキュメントはありません。ソースコードを読んでください。

于 2009-09-13T23:14:29.813 に答える