首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Java语言中为Serpent生成PBEKey?

如何在Java语言中为Serpent生成PBEKey?
EN

Stack Overflow用户
提问于 2011-08-05 16:24:46
回答 1查看 2K关注 0票数 3

我正在尝试支持PBE for AES,Serpent和TwoFish。目前,我可以使用BC在Java中生成一个AES PBEKey,如下所示:

代码语言:javascript
复制
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC", provider);
PBEKeySpec pbeKeySpec = new PBEKeySpec("Password12".toCharArray());
SecretKey key = factory.generateSecret(pbeKeySpec);

但是我不知道如何为Serpent生成PBEKey,所以我假设它不可能开箱即用。我该如何去实现它呢?有没有一个钩子,我可以注册我自己的SecretKeyFactory来处理蛇键?

巧合的是,我注意到使用AES PBEKey (如上所述)对毒蛇/TwoFish进行加密/解密是“有效的”,但我不知道会有什么影响。我可以使用AES PBEKey吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-08-10 12:49:48

在与PaŭloEbermann (如上)讨论后,我提出了以下解决方案。它为AES256生成一个PBE密钥,然后简单地将所需的字节数从生成的密钥复制到一个新的SecretKeySpec()中,这允许我指定所需的算法和密钥长度。目前,我正在对密码加盐,并在每次调用加密时创建一个随机IV。我的假设是IV是不必要的,因为每个加密消息都应用了随机盐,但我不是100%确定的,所以我还是添加了IV。我希望有人能证实或否认这个假设,因为如果不需要IV,那么它就会毫无理由地膨胀encrypt()的输出大小。理想情况下,我可以生成一个没有算法约束的可变长度的PBEKey (根据PKCS5),但似乎我被绑定到由所选提供商提供的可用的PBE方案中定义的密钥大小。因此,这个实现必须使用BouncyCastle,因为我找不到从标准JCE提供者那里提供至少256位密钥的PBE方案。

代码语言:javascript
复制
/**
 * parts of this code were copied from the StandardPBEByteEncryptor class from the Jasypt (www.jasypt.org) project
 */
public class PBESample {
    private final String KEY_ALGORITHM = "PBEWithSHA256And256BitAES-CBC-BC";
    private final String MODE_PADDING = "/CBC/PKCS5Padding";
    private final int DEFAULT_SALT_SIZE_BYTES = 16;
    
    private final SecureRandom rand;
    
    private final String passwd = "(Password){12}<.....>!";

    public PBESample() throws Exception {
        rand = SecureRandom.getInstance("SHA1PRNG");
    }
    
    private byte[] generateSalt(int size) {
        byte[] salt = new byte[size];
        rand.nextBytes(salt);
        
        return salt;
    }
    
    private SecretKey generateKey(String algorithm, int keySize, byte[] salt) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException{
        SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray(), salt, 100000);
        SecretKey tmpKey = factory.generateSecret(pbeKeySpec);
        byte[] keyBytes = new byte[keySize / 8];
        System.arraycopy(tmpKey.getEncoded(), 0, keyBytes, 0, keyBytes.length);
        
        return new SecretKeySpec(keyBytes, algorithm);
    }
    
    private byte[] generateIV(Cipher cipher) {
        byte[] iv = new byte[cipher.getBlockSize()];
        rand.nextBytes(iv);
        
        return iv;
    }

    private byte[] appendArrays(byte[] firstArray, byte[] secondArray) {
        final byte[] result = new byte[firstArray.length + secondArray.length];
        
        System.arraycopy(firstArray, 0, result, 0, firstArray.length);
        System.arraycopy(secondArray, 0, result, firstArray.length, secondArray.length);
        
            return result;
    }

    
    public byte[] encrypt(String algorithm, int keySize, final byte[] message) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithm + MODE_PADDING);

        // The salt size for the chosen algorithm is set to be equal 
        // to the algorithm's block size (if it is a block algorithm).
        int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
        int algorithmBlockSize = cipher.getBlockSize();
        if (algorithmBlockSize > 0) {
            saltSizeBytes = algorithmBlockSize;
        }

        // Create salt
        final byte[] salt = generateSalt(saltSizeBytes);

        SecretKey key = generateKey(algorithm, keySize, salt);

        // create a new IV for each encryption
        final IvParameterSpec ivParamSpec = new IvParameterSpec(generateIV(cipher));

        // Perform encryption using the Cipher
        cipher.init(Cipher.ENCRYPT_MODE, key, ivParamSpec);
        byte[] encryptedMessage = cipher.doFinal(message);

        // append the IV and salt
        encryptedMessage = appendArrays(ivParamSpec.getIV(), encryptedMessage);
        encryptedMessage = appendArrays(salt, encryptedMessage);

        return encryptedMessage;
    }
    
    public byte[] decrypt(String algorithm, int keySize, final byte[] encryptedMessage) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithm + MODE_PADDING);
        
        // determine the salt size for the first layer of encryption
        int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
        int algorithmBlockSize = cipher.getBlockSize();
        if (algorithmBlockSize > 0) {
            saltSizeBytes = algorithmBlockSize;
        }
        
        byte[] decryptedMessage = new byte[encryptedMessage.length];
        System.arraycopy(encryptedMessage, 0, decryptedMessage, 0, encryptedMessage.length);

        // extract the salt and IV from the incoming message
        byte[] salt = null;
        byte[] iv = null;
        byte[] encryptedMessageKernel = null;
        final int saltStart = 0;
        final int saltSize = (saltSizeBytes < decryptedMessage.length ? saltSizeBytes : decryptedMessage.length);
        final int ivStart = (saltSizeBytes < decryptedMessage.length ? saltSizeBytes : decryptedMessage.length);
        final int ivSize = cipher.getBlockSize();
        final int encMesKernelStart = (saltSizeBytes + ivSize < decryptedMessage.length ? saltSizeBytes + ivSize : decryptedMessage.length);
        final int encMesKernelSize = (saltSizeBytes + ivSize < decryptedMessage.length ? (decryptedMessage.length - saltSizeBytes - ivSize) : 0);

        salt = new byte[saltSize];
        iv = new byte[ivSize];
        encryptedMessageKernel = new byte[encMesKernelSize];

        System.arraycopy(decryptedMessage, saltStart, salt, 0, saltSize);
        System.arraycopy(decryptedMessage, ivStart, iv, 0, ivSize);
        System.arraycopy(decryptedMessage, encMesKernelStart, encryptedMessageKernel, 0, encMesKernelSize);
        
        SecretKey key = generateKey(algorithm, keySize, salt);
        
        IvParameterSpec ivParamSpec = new IvParameterSpec(iv);

        // Perform decryption using the Cipher
        cipher.init(Cipher.DECRYPT_MODE, key, ivParamSpec);
        decryptedMessage = cipher.doFinal(encryptedMessageKernel);

        // Return the results
        return decryptedMessage;
    }

    public static void main(String[] args) throws Exception {
        // allow the use of the BC JCE
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        
        final String message = "Secret Message";
        PBESample engine = new PBESample();
        
        byte[] encryptedMessage = engine.encrypt("AES", 128, message.getBytes());
        byte[] decryptedMessage = engine.decrypt("AES", 128, encryptedMessage);
        if (message.equals(new String(decryptedMessage))) {
            System.out.println("AES OK");
        }
        
        encryptedMessage = engine.encrypt("Serpent", 256, message.getBytes());
        decryptedMessage = engine.decrypt("Serpent", 256, encryptedMessage);
        if (message.equals(new String(decryptedMessage))) {
            System.out.println("Serpent OK");
        }
        
        encryptedMessage = engine.encrypt("TwoFish", 256, message.getBytes());
        decryptedMessage = engine.decrypt("TwoFish", 256, encryptedMessage);
        if (message.equals(new String(decryptedMessage))) {
            System.out.println("TwoFish OK");
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6953431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档