문제

openssl 라이브러리(DES 암호화)를 사용하여 암호화/암호 해독을 제공하는 레거시 C++ 모듈이 있습니다.해당 코드를 Java로 변환하려고 하는데 DLL, JNI 등에 의존하고 싶지 않습니다.C++ 코드는 다음과 같습니다.

des_string_to_key(reinterpret_cast<const char *>(key1), &initkey);
des_string_to_key(reinterpret_cast<const char *>(key2), &key);
key_sched(&key, ks);
// ...
des_ncbc_encrypt(reinterpret_cast<const unsigned char *>(tmp.c_str()), 
reinterpret_cast< unsigned char *>(encrypted_buffer), tmp.length(), ks, &initkey, 
DES_ENCRYPT);

return base64(reinterpret_cast<const unsigned char *>(encrypted_buffer),    strlen(encrypted_buffer));

Java 코드는 다음과 같습니다.

Cipher ecipher;
try {
    ecipher = Cipher.getInstance("DES");
    SecretKeySpec keySpec = new SecretKeySpec(key, "DES");      
    ecipher.init(Cipher.ENCRYPT_MODE, keySpec);         
    byte[] utf8 = password.getBytes("UTF8");
    byte[] enc = ecipher.doFinal(utf8);
    return new sun.misc.BASE64Encoder().encode(enc);
}
catch {
    // ...
}

그러면 Java에서는 꽤 쉽게 DES 암호화를 할 수 있는데, 완전히 다른 메소드를 사용하여 위 코드와 동일한 결과를 어떻게 얻을 수 있을까요?특히 나를 괴롭히는 것은 C++ 버전이 2개의 키를 사용하는 반면 Java 버전은 1개의 키만 사용한다는 사실입니다.CBC 모드의 DES에 대한 답변은 상당히 만족스럽지만 아직 작동시킬 수는 없습니다.원본 코드에 대한 자세한 내용은 다음과 같습니다.서명되지 않은 문자 키1[10]= {0};서명되지 않은 문자 키2[50]= {0};

int i;
for (i=0;i<8;i++)
    key1[i] = 31+int((i*sqrt((double)i*5)))%100;
key1[9]=0;

for (i=0;i<48;i++)
    key2[i] = 31+int((i*i*sqrt((double)i*2)))%100;
key2[49]=0;
...
// Initialize encrypted buffer
memset(encrypted_buffer, 0, sizeof(encrypted_buffer));

// Add begin Text and End Text to the encrypted message
std::string input;
const char beginText = 2;
const char endText = 3;
input.append(1,beginText);
input.append(bufferToEncrypt);
input.append(1,endText);    

// Add padding
tmp.assign(desPad(input));

des_ncbc_encrypt(reinterpret_cast<const unsigned char *>(tmp.c_str()),     
reinterpret_cast< unsigned char *>(encrypted_buffer), tmp.length(), ks, &initkey, 
DES_ENCRYPT);
...

내가 읽은 바에 따르면 키의 길이는 56(또는 64, 나에게는 명확하지 않음) 비트여야 하지만 여기서는 48바이트입니다.

도움이 되었습니까?

해결책

저는 OpenSSL 전문가는 아니지만 C++ 코드가 CBC 모드에서 DES를 사용하므로 IV가 필요할 것 같습니다(이것이 바로 initKey이고 이것이 바로 두 개의 키가 필요하다고 생각하는 이유입니다).내 말이 맞다면 CBC 모드에서도 DES를 사용하도록 Java 코드를 변경해야 합니다. 그러면 Java 코드에도 암호화 키와 IV가 필요합니다.

다른 팁

또한 코드에서 sun.misc.* 클래스를 사용하면 안 된다는 점을 명심하세요.이는 공개 API가 아니기 때문에 다른 VM에서 중단될 수 있습니다.Apache Commons 코덱(다른 것 중에서)에는 이 문제를 해결하지 않는 Base64 구현이 있습니다.

단일 DES가 왜 여러 키를 사용하는지 잘 모르겠습니다.Triple-DES를 사용하더라도 Java Cryptography API와 함께 별도의 키를 사용하는 대신 단일 키(더 많은 데이터 바이트 포함)를 사용할 것이라고 생각합니다.

알고리즘은 일치해야 합니다.다른 결과를 얻는다면 키와 텍스트를 처리하는 방식과 관련이 있을 수 있습니다.또한 Java 문자의 길이는 2바이트이고 C++ 문자의 길이는 1바이트이므로 이와 관련이 있을 수 있다는 점을 명심하세요.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top