2016-11-01 20 views
2

を投げる私はPBEWITHHMACSHA256ANDAES_256アルゴリズムを使用したいが、それはサポートされていません。私はそれが無駄ではなく動作します期待して私のテストにbouncy castleプロバイダを追加しました。誰もがPBEWITHHMACSHA256ANDAESSupportedリストに追加されるように、以下のテストを修正する方法を教えていただけますか?PBEWITHHMACSHA256ANDAES_256暗号化がEncryptionOperationNotPossibleException

import java.security.Security; 
import java.util.Set; 
import java.util.TreeSet; 

import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; 
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; 
import org.jasypt.exceptions.EncryptionOperationNotPossibleException; 
import org.jasypt.registry.AlgorithmRegistry; 
import org.junit.Assert; 
import org.junit.BeforeClass; 
import org.junit.Test; 

public class EncryptionTest { 
    @BeforeClass 
    public static void beforeClass() { 
     Security.addProvider(new BouncyCastleProvider()); 
    } 

    @Test 
    public void test() { 
     Set<String> supported = new TreeSet<>(); 
     Set<String> unsupported = new TreeSet<>(); 
     for (Object oAlgorithm : AlgorithmRegistry.getAllPBEAlgorithms()) { 
      String algorithm = (String) oAlgorithm; 
      try { 
       SimpleStringPBEConfig pbeConfig = new SimpleStringPBEConfig(); 
       pbeConfig.setAlgorithm(algorithm); 
       pbeConfig.setPassword("changeme"); 
       StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); 
       encryptor.setConfig(pbeConfig); 

       String encrypted = encryptor.encrypt("foo"); 
       String decrypted = encryptor.decrypt(encrypted); 
       Assert.assertEquals("foo", decrypted); 
       supported.add(algorithm); 
      } catch (EncryptionOperationNotPossibleException e) { 
       unsupported.add(algorithm); 
      } 
     } 
     System.out.println("Supported"); 
     supported.forEach((String alg) -> System.out.println(" " + alg)); 
     System.out.println("Unsupported"); 
     unsupported.forEach((String alg) -> System.out.println(" " + alg)); 
    } 
}    

出力:

Supported 
    PBEWITHMD2ANDDES 
    PBEWITHMD5AND128BITAES-CBC-OPENSSL 
    PBEWITHMD5AND192BITAES-CBC-OPENSSL 
    PBEWITHMD5AND256BITAES-CBC-OPENSSL 
    PBEWITHMD5ANDDES 
    PBEWITHMD5ANDRC2 
    PBEWITHSHA1ANDDES 
    PBEWITHSHA1ANDDESEDE 
    PBEWITHSHA1ANDRC2 
    PBEWITHSHA1ANDRC2_128 
    PBEWITHSHA1ANDRC2_40 
    PBEWITHSHA1ANDRC4_128 
    PBEWITHSHA1ANDRC4_40 
Unsupported 
    PBEWITHHMACSHA1ANDAES_128 
    PBEWITHHMACSHA1ANDAES_256 
    PBEWITHHMACSHA224ANDAES_128 
    PBEWITHHMACSHA224ANDAES_256 
    PBEWITHHMACSHA256ANDAES_128 
    PBEWITHHMACSHA256ANDAES_256 
    PBEWITHHMACSHA384ANDAES_128 
    PBEWITHHMACSHA384ANDAES_256 
    PBEWITHHMACSHA512ANDAES_128 
    PBEWITHHMACSHA512ANDAES_256 
    PBEWITHMD5ANDTRIPLEDES 
    PBEWITHSHA256AND128BITAES-CBC-BC 
    PBEWITHSHA256AND192BITAES-CBC-BC 
    PBEWITHSHA256AND256BITAES-CBC-BC 
    PBEWITHSHAAND128BITAES-CBC-BC 
    PBEWITHSHAAND128BITRC2-CBC 
    PBEWITHSHAAND128BITRC4 
    PBEWITHSHAAND192BITAES-CBC-BC 
    PBEWITHSHAAND2-KEYTRIPLEDES-CBC 
    PBEWITHSHAAND256BITAES-CBC-BC 
    PBEWITHSHAAND3-KEYTRIPLEDES-CBC 
    PBEWITHSHAAND40BITRC2-CBC 
    PBEWITHSHAAND40BITRC4 
    PBEWITHSHAANDIDEA-CBC 
    PBEWITHSHAANDTWOFISH-CBC 

*編集*

@EbbeMPedersenは、このアルゴリズムは、SunJCEにより提供されるが、私はSunJCEプロバイダは、次のコード

を使用して有効になっていることを確認できることが示唆されました
for (Provider provider : Security.getProviders()) { 
    System.out.println(provider.getName() + " " + provider.getClass().getName()); 
} 

出力

SUN sun.security.provider.Sun 
SunRsaSign sun.security.rsa.SunRsaSign 
SunEC sun.security.ec.SunEC 
SunJSSE com.sun.net.ssl.internal.ssl.Provider 
SunJCE com.sun.crypto.provider.SunJCE 
SunJGSS sun.security.jgss.SunProvider 
SunSASL com.sun.security.sasl.Provider 
XMLDSig org.jcp.xml.dsig.internal.dom.XMLDSigRI 
SunPCSC sun.security.smartcardio.SunPCSC 
SunMSCAPI sun.security.mscapi.SunMSCAPI 
BC org.bouncycastle.jce.provider.BouncyCastleProvider 
+0

はBouncyCastleを見ては[こちら]アルゴリズム(https://www.bouncycastle.org/specifications.html)をサポート。.. PBEWITHHMACSHA256ANDAES_256がリストに含まれていません。それは、例えばだ、別のセキュリティプロバイダ –

+0

からリストにポップアップ表示可能性があります[SunJCE]の一部(http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#SunJCEProvider) –

+0

私の編集 'com.sun.crypto.provider.SunJCEをご覧ください'は、' Security.getProviders() 'によって返された配列内にあります。 –

答えて

0

私は問題がJasyptが派生AlgorithmParametersを保持し、ENCRYPTDECRYPT間の暗号を切り替えるときにそれらを再使用することはできないということだと思います。 Jasyptが隠蔽している根本的な例外はjava.security.InvalidAlgorithmParameterException: Missing parameter type: IV expectedですが、salt(またはこの場合はSaltGenerator)とkey obtention iterations(つまりHMAC/SHA-256を呼び出す回数)を指定すると、Jasyptはそれでも計算されたパラメータを解読暗号に渡す方法を理解する。

encryptCipher.getParameters().getEncoded() -> 306206092a864886f70d01050d3055303406092a864886f70d01050c30270410f5a439e8dc12642972dbbf3e1867edaf020203e8020120300c06082a864886f70d02090500301d060960864801650304012a0410caacd97ae953ae257b1b4a0bb70ccc2e 
はそれを確認するために、表現のウィンドウを使用し、ここであなたは根本的な例外をキャッチすることができます - (あなたが)あなたのテストをデバッグし、ライン 1055(Jasypt 1.9.2で StandardPBEByteEncryptor.javaにブレークポイントを置くことによってこれを確認することができます)

しかし、ここで

decryptCipher.getParameters().getEncoded() -> java.security.ProviderException: Could not construct CipherSpi instance 

がJasyptの失敗と、ご希望のアルゴリズムを使用しての成功した方法を実証(Groovyの)テストです( ノートは:1000回の反復は、最新のハードウェアに対する堅牢なセキュリティのためには十分ではありませんが、ためにデモンストレーションのみ)ポーズ:

@Test 
void testShouldUseHS256andAES256() { 
    // Arrange 
    String algorithm = "PBEwithHMACSHA256andAES_256"; 
    SimpleStringPBEConfig pbeConfig = new SimpleStringPBEConfig(); 
    pbeConfig.setAlgorithm(algorithm); 
    pbeConfig.setPassword("changeme"); 

    // Need an IV (derived from salt and iteration count) 
    // pbeConfig.setKeyObtentionIterations(1000); 
    // pbeConfig.setSaltGenerator(new RandomSaltGenerator()); 

    StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); 
    encryptor.setConfig(pbeConfig); 

    // Act 
    def msg = shouldFail(Exception) { 
     String encrypted = encryptor.encrypt("foo"); 

     // Assert 
     String decrypted = encryptor.decrypt(encrypted); 
     Assert.assertEquals("foo", decrypted); 
    } 
    logger.info("Expected: ${msg}") 

    // Required way 
    Cipher rawCipher = Cipher.getInstance(algorithm) 
    PBEKeySpec pbeKeySpec = new PBEKeySpec("changeme" as char[]) 
    final SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm); 
    SecretKey tempKey = factory.generateSecret(pbeKeySpec); 
    PBEParameterSpec saltParameterSpec = new PBEParameterSpec(Hex.decodeHex("ABCDEF" as char[]), 1000) 
    rawCipher.init(Cipher.ENCRYPT_MODE, tempKey, saltParameterSpec) 

    // Save the generated ASN.1-encoded parameters 
    byte[] algorithmParameterBytes = rawCipher.getParameters().encoded 

    byte[] cipherBytes = rawCipher.doFinal("foo".getBytes(StandardCharsets.UTF_8)) 

    AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(algorithm) 
    algorithmParameters.init(algorithmParameterBytes) 
    rawCipher.init(Cipher.DECRYPT_MODE, tempKey, algorithmParameters) 
    byte[] plainBytes = rawCipher.doFinal(cipherBytes) 
    String recovered = new String(plainBytes, StandardCharsets.UTF_8) 

    assert recovered == "foo" 
}