2016-09-20 25 views
0

JavaからC++にアプリケーションを移植する必要があります。私はAES CTR 128の問題についています。JavaとCでは異なる暗号化結果を持っています。私のJavaコード。Javaとopenssl Cが異なるAES CTR暗号化結果

import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 
import java.util.Base64; 


class HelloWorld { 
    public static void main(String[] args) { 
     try 
     { 

      byte[] keyBytes = Base64.getDecoder().decode("5gYDRl00XcjqlcC5okdBSfDx46HIGZBMAvMiibVYixc="); 
      byte[] ivBytes = Base64.getDecoder().decode("AAAAAAAAAAAAAAAAAAAAAA=="); 

      SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); 
      IvParameterSpec iv = new IvParameterSpec(ivBytes); 

      Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); 
      cipher.init(Cipher.ENCRYPT_MODE, key, iv); 
      String encrypted = Base64.getEncoder().encodeToString(cipher.doFinal("This is a plaintext message.".getBytes())); 
      System.out.println(encrypted); // print: sTBJYaaGNTxCErAXbP6eXnU59Yyn1UJAp7MGQw== 

     } catch (Exception e) {} 
     return; 
    } 
} 

My Cコード。私は同じalgorythm、プレーンテキスト、キー、およびivを使用します。しかし、別の暗号テキストの結果を得る。

#include <openssl/conf.h> 
#include <openssl/bio.h> 
#include <openssl/buffer.h> 
#include <openssl/evp.h> 
#include <stdio.h> 
#include <string.h> 

char *base64encode (const void *b64_encode_this, int encode_this_many_bytes) 
{ 
    BIO *b64_bio, *mem_bio;  //Declares two OpenSSL BIOs: a base64 filter and a memory BIO. 
    BUF_MEM *mem_bio_mem_ptr; //Pointer to a "memory BIO" structure holding our base64 data. 
    b64_bio = BIO_new(BIO_f_base64());      //Initialize our base64 filter BIO. 
    mem_bio = BIO_new(BIO_s_mem());       //Initialize our memory sink BIO. 
    BIO_push(b64_bio, mem_bio);   //Link the BIOs by creating a filter-sink BIO chain. 
    BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //No newlines every 64 characters or less. 
    BIO_write(b64_bio, b64_encode_this, encode_this_many_bytes); //Records base64 encoded data. 
    BIO_flush(b64_bio); //Flush data. Necessary for b64 encoding, because of pad characters. 
    BIO_get_mem_ptr(mem_bio, &mem_bio_mem_ptr); //Store address of mem_bio's memory structure. 
    BIO_set_close(mem_bio, BIO_NOCLOSE); //Permit access to mem_ptr after BIOs are destroyed. 
    BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one). 
    BUF_MEM_grow(mem_bio_mem_ptr, (*mem_bio_mem_ptr).length + 1); //Makes space for end null. 
    (*mem_bio_mem_ptr).data[(*mem_bio_mem_ptr).length] = '\0'; //Adds null-terminator to tail. 
    return (*mem_bio_mem_ptr).data; //Returns base-64 encoded data. (See: "buf_mem_st" struct). 
} 

char *base64decode (const void *b64_decode_this, int decode_this_many_bytes) 
{ 
    BIO *b64_bio, *mem_bio;  //Declares two OpenSSL BIOs: a base64 filter and a memory BIO. 
    char *base64_decoded = calloc((decode_this_many_bytes*3)/4+1, sizeof(char)); //+1 = null. 
    b64_bio = BIO_new(BIO_f_base64());      //Initialize our base64 filter BIO. 
    mem_bio = BIO_new(BIO_s_mem());       //Initialize our memory source BIO. 
    BIO_write(mem_bio, b64_decode_this, decode_this_many_bytes); //Base64 data saved in source. 
    BIO_push(b64_bio, mem_bio);   //Link the BIOs by creating a filter-source BIO chain. 
    BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL);   //Don't require trailing newlines. 
    int decoded_byte_index = 0; //Index where the next base64_decoded byte should be written. 
    while (0 < BIO_read(b64_bio, base64_decoded+decoded_byte_index, 1)){ //Read byte-by-byte. 
     decoded_byte_index++; //Increment the index until read of BIO decoded data is complete. 
    } //Once we're done reading decoded data, BIO_read returns -1 even though there's no error. 
    BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one). 
    return base64_decoded;  //Returns base-64 decoded data with trailing null terminator. 
} 

int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) 
{ 
    EVP_CIPHER_CTX *ctx; 

    int len; 

    int ciphertext_len; 

    /* Create and initialise the context */ 
    ctx = EVP_CIPHER_CTX_new(); 

    /* Initialise the encryption operation */ 
    EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv); 

    /* Provide the message to be encrypted, and obtain the encrypted output. 
    * EVP_EncryptUpdate can be called multiple times if necessary 
    */ 
    EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len); 
    ciphertext_len = len; 

    /* Finalise the encryption. Further ciphertext bytes may be written at 
    * this stage. 
    */ 
    EVP_EncryptFinal_ex(ctx, ciphertext + len, &len); 
    ciphertext_len += len; 

    /* Clean up */ 
    EVP_CIPHER_CTX_free(ctx); 

    return ciphertext_len; 
} 

int main (void) 
{ 
    /* A 256 bit key */ 
    char keyStr[] = "5gYDRl00XcjqlcC5okdBSfDx46HIGZBMAvMiibVYixc="; 
    unsigned char *key = (unsigned char *)base64decode(keyStr, strlen(keyStr)); 

    /* A 128 bit IV */ 
    char ivStr[] = "AAAAAAAAAAAAAAAAAAAAAA=="; 
    unsigned char *iv = (unsigned char *)base64decode(ivStr, strlen(ivStr)); 

    /* Message to be encrypted */ 
    unsigned char *plaintext = (unsigned char *)"This is a plaintext message."; 

    /* Buffer for ciphertext */ 
    unsigned char ciphertext[128]; 
    int ciphertext_len; 

    /* Initialise the library */ 
    OpenSSL_add_all_algorithms(); 
    OPENSSL_config(NULL); 

    /* Encrypt the plaintext */ 
    ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv, 
           ciphertext); 

    /* Encode with Base64 */ 
    char *ciphertextBase64 = base64encode(ciphertext, strlen(ciphertext)); 
    printf("Ciphertext is: %s\n", ciphertextBase64); /* print: UL4lvWZNtDVO64ywHVkFM/uBv+lpE3DhGZrRcw== */ 

    /* Clean up */ 
    EVP_cleanup(); 

    return 0; 
} 

どのように私は同じ結果を得ることができますsTBJYaaGNTxCErAXbP6eXnU59Yyn1UJAp7MGQw==

+1

OpenSSLでは 'AES_encrypt'とフレンドを使用しないでください。これはソフトウェアのみの実装なので、AES-NIなどのハードウェアサポートは受けられません。あなたは 'EVP_ *'関数を使っていなければなりません。 OpenSSL wikiの[EVP Symmetric Encryption and Decryption](http://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption)を参照してください。 – jww

+0

EVP_ *関数でCコードを書き直しました。とにかく私は間違った暗号文を得た。 –

+1

OpenSSLはパディングを追加する可能性が高いです。それは最後のブロックを期待してはいけませんが、私はそれまでに得られていない印象を受けます。チェックアウト[EVP_CIPHER_CTX_set_padding](https://www.openssl.org/docs/manmaster/crypto/EVP_EncryptInit.html)。あなたの直面する問題は、Base64文字列を解読することだと思います。あなたはntotにそれらについての何かを述べました、その唯一の推測です。おそらく、あなたはバックアップし、いくつかのハードコードされたキーと静脈を使用する必要がありますか? – jww

答えて

0

ここではAES CTR 256ではなく128です。Javaは明示的にはそれが暗黙的にキーサイズから取得するビットを定義しません。だからここで鍵サイズは32バイト〜256ビットです。私は誤ってここでAES CTR 128と考えています。

関連する問題