Bertold wrote:

Hi,

I am trying to use password based encryption, and got a code working.
My problem is that if I feed the same parameters (password, salt,
iteration count) into an equivalent code written in Java (and using Sun
JRE 1.4.2), then the result of the encryption will be different.

I could not quite figure out why there is a difference.

Below you can find the Java code using the standard JCE shipped with
Java 1.4, and the code using NSS.

As an exampe, here is the result of encrypting the string "test" with
the 2 different implementations.

$ ./pbe test
calling encrypt:  0x36 0xb5 0xc5 0x39 0x5c 0x72 0x71 0x26

$ java -cp . PBE test
calling encrypt():  0xca 0xa6 0x8f 0xb3 0x77 0x36 0xe9 0x8a

I would appreciate any help.

Thanks,
Bertold



My first suspicion would be one or the other is converting the password to Unicode before using it.

bob

PBE.cpp:
--------
#include "PBE.hpp"
#include <nss.h>
#include <stdio.h>

const unsigned char * const PBE::_pbeRawPassword = (unsigned char
*)"testPassword";
const int PBE::_pbeRawPasswordLength = 12;
const SECItem PBE::_pbePassword = { siClearDataBuffer, (unsigned char
*)_pbeRawPassword, _pbeRawPasswordLength };

const unsigned char PBE::_pbeRawSalt[] = { 1,2,3,4,5,6,7,8 };
const SECItem PBE::_pbeSalt = { siClearDataBuffer, (unsigned char
*)_pbeRawSalt, 8 /* salt length */};

const int PBE::_iterationCount = 1000;

PBE::PBE(const unsigned char * const data, int len) :
 _data(NULL),
 _slot(NULL)

{
 _data = data;
 _len = len;
 _slot = PK11_GetInternalSlot();
}

void
PBE::encrypt()
{
 unsigned char paddedData[4096];
 int paddedDataLen;
 unsigned char encryptedData[4096];
 int encryptedDataLen;
 PK11Context * context;
 SECAlgorithmID * pbeSecAlgorithmId =
PK11_CreatePBEAlgorithmID(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
                                                                 
_iterationCount,
                                                                 (SECItem 
*)&_pbeSalt);

 PK11SymKey * pbeKey = PK11_PBEKeyGen(_slot, pbeSecAlgorithmId,
                                       (SECItem *)&_pbePassword,
                                       PR_FALSE,
                                       NULL);

 context = PK11_CreateContextBySymKey(CKM_DES_CBC,
                                       CKA_ENCRYPT,
                                       pbeKey,
                                       (SECItem *)&_pbeSalt);



 addPadding(_data, _len, paddedData, &paddedDataLen);

 PK11_CipherOp(context,
                encryptedData,
                &encryptedDataLen,
                paddedDataLen, // maximum data length
                paddedData,
                paddedDataLen);

 PK11_Finalize(context);

 PK11_DestroyContext(context, PR_TRUE);

 printByteArray(encryptedData, encryptedDataLen);
}

void
PBE::addPadding(const unsigned char * const src,
                int srcLen,
                unsigned char * dst,
                int * dstLen)
{
 int i = 0;
 unsigned char padChar = 8 - (srcLen % 8);
 memmove((void *)dst, src, srcLen);
 for (i=0; i<padChar; i++) {
   dst[srcLen + i] = padChar;
 }
 *dstLen = srcLen + padChar;
}

void
PBE::printByteArray(const unsigned char * const data, int len)
{
 int i = 0;
 char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };

 for (i=0; i<len; i++) {
   unsigned char c = data[i];
   printf(" 0x%c%c", hexChars[c >> 4], hexChars[c & 0x0f]);
 }
 printf("\n");
}

int
main(int argc, char *argv[])
{
 PBE * p = NULL;
 if (argc != 2) {
   fprintf(stderr, "usage: pbe <password to encrypt>\n");
   return -1;
 }

 NSS_NoDB_Init("/tmp");

 p = new PBE((unsigned char *)argv[1], strlen(argv[1]));
 printf("calling encrypt: ");
 p->encrypt();

 return 0;
}

PBE.hpp:
--------
#include <pk11func.h>

class PBE {
public:
 PBE(const unsigned char * const data, int len);
 virtual void encrypt();

private:
 static void printByteArray(const unsigned char * const data, int
len);
 static void addPadding(const unsigned char * const src,
                         int srcLen,
                         unsigned char * dst,
                         int * dstLen);
 const unsigned char * _data;
 int _len;
 PK11SlotInfo * _slot;

 static const unsigned char * const _pbeRawPassword;
 static const int _pbeRawPasswordLength;
 static const SECItem _pbePassword;
 static const unsigned char _pbeRawSalt[8];
 static const SECItem _pbeSalt;
 static const int _iterationCount;

 PBE(const PBE& string);
 PBE& operator=(const PBE& string);
};


PBE.java: --------- import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKey; import javax.crypto.spec.PBEParameterSpec; import javax.crypto.spec.PBEKeySpec; import java.security.spec.KeySpec; import java.security.spec.AlgorithmParameterSpec;

public class PBE {
   private static final char[] password =
"testPassword".toCharArray();
   private static final byte[] salt = { 1, 2, 3, 4, 5, 6, 7, 8 };
   private static final int iterationCount = 1000;
   private static final String algorithm = "PBEWithMD5AndDES";

   private byte[] _data = null;

   public PBE(String data) {
       _data = data.getBytes();
   }

   public void encrypt() throws Exception {
       Cipher cipher = Cipher.getInstance(algorithm);
       SecretKeyFactory factory =
SecretKeyFactory.getInstance(algorithm);
       // create keyspec without passing in salt and iteration count
       KeySpec keySpec = new PBEKeySpec(password);
       SecretKey key = factory.generateSecret(keySpec);

       // create algorithm parameters using the salt and the iteration
count
       AlgorithmParameterSpec pbeParams = new PBEParameterSpec(salt,
iterationCount);

       // initialize cipher with key and algorithm parameters
       cipher.init(Cipher.ENCRYPT_MODE, key, pbeParams);
       printByteArray(cipher.doFinal(_data));
   }

   public static void printByteArray(byte[] data) {
       final char[] hexChars = "0123456789abcdef".toCharArray();

       for (int i=0; i<data.length; i++) {
           int b = data[i];
           if (b < 0) {
               b = 256 + b;
           }
           System.out.print(" 0x");
           System.out.print(hexChars[b >> 4]);
           System.out.print(hexChars[0x0f & b]);
       }
       System.out.println();
   }

   public static void main(String[] args) throws Exception {
       if (args.length != 1) {
           System.err.println("usage: PBE <string to encrypt>");
       }
       PBE p = new PBE(args[0]);
       System.out.print("calling encrypt(): ");
       p.encrypt();
   }
}

_______________________________________________
mozilla-crypto mailing list
[email protected]
http://mail.mozilla.org/listinfo/mozilla-crypto




Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to