Como você usa a biblioteca cripta em C para a criptografia DES? (setkey, criptografado, cripta, etc.)
-
07-07-2019 - |
Pergunta
Preciso fazer alguma criptografia de DES simples em C para interagir com algum código antigo. Pelo que eu entendo, você pode usar a biblioteca "cripta" para isso, com as funções setkey, criptografando, cripta etc. Eu tenho mexido com ela e não consigo acertar. Falta o exemplo na página do homem para setkey/criptografia.
Quero obter a mesma saída que seria capaz de obter com algum código Java (veja abaixo).
Então, digamos que eu tenho duas matrizes de personagens em C.
char *message = "hellothe";
char *key = "iamakey0";
Alguém pode dar um exemplo de como criptografá -los com o setkey/criptografar e obter o mesmo resultado que eu faria com o código Java? Sei que você precisa colocar mensagem e chave em uma matriz de 64 bytes, onde cada char representa um pouco, mas parte disso também é confusa. Aparentemente, você tem que acertar a paridade nisso ou algo assim?
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;
}
Solução
Porque você está ligando Cipher.getInstance
Com apenas a corda "DES"
, você não está especificando um modo cifra ou método de preenchimento. Isso significa que você obtém os padrões, o que depende do que o provedor de criptografia Java que você está usando - você precisa saber exatamente o que eles devem escrever C. compatíveis (você realmente deve especificá -los em vez de confiar nos padrões).
Se você estiver usando o provedor SUNJCE, os padrões para o DES são o Modo BCE e o PKCS #5 preenchimento. A melhor maneira de fazer isso provavelmente é usar o OpenSSL ou outra biblioteca de criptografia carnuda - mas se você quiser usar funções que geralmente são encontradas na biblioteca C padrão em plataformas do tipo Unix, o ecb_crypt
Família de funções será muito mais fácil de trabalhar do que o setkey
/ encrypt
família.
Você precisará adicionar o PKCS#5 preenchido ao criptografar e verificar (e descartá -lo) ao descriptografar). A seguir ecb_pkcs5_encrypt
A função deve fazer o equivalente aproximado do código Java acima usando essas funções.
/* 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;
}
Outras dicas
Não use Crypt (). Ele usa algum algoritmo não padrão, por isso será muito difícil interoperar com outros sistemas. Além disso, o DES não é seguro de qualquer maneira.
Sugiro que você use o OpenSSL em C. A maioria de suas cifras é compatível com o JCE.
Se você realmente tem que usar o Crypt, o Sun's Jre vem com uma aula para lidar com cripta,
com.sun.security.auth.module.Crypt
Esta é a classe interna, então a documentação não está lá. Basta ler o código -fonte.