【问题标题】:Flexiprovider - How to encrypt/de with formatted keypairFlexiprovider - 如何使用格式化的密钥对加密/解密
【发布时间】:2015-03-12 09:23:11
【问题描述】:

我使用 flexiprovider 使用基于椭圆曲线的非对称算法进行加密/解密,遵循 tutorial。稍作修改,我将出于个人目的(例如存储到数据库或文本文件中)将公钥和私钥转换为 Base64。我也在看这个question,答案是参考这个thread。但是我的代码是为 dekstop 而不是在 android 设备中运行,我认为 java 中的 android 和 dekstop 版本有很大的不同(只是为了清理我的问题信息)。好的,在我的代码中,当我要从生成的公钥创建格式化的公钥时出现错误(我认为当我尝试为私钥执行此操作时会发生同样的问题)。 现在,这是我的代码:

  • 密钥对生成器类。
import org.jivesoftware.smack.util.Base64; //or whatever to convert into Base64
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.KeyFactory;
import javax.crypto.Cipher;   
import de.flexiprovider.common.ies.IESParameterSpec;
import de.flexiprovider.core.FlexiCoreProvider;
import de.flexiprovider.ec.FlexiECProvider;
import de.flexiprovider.ec.parameters.CurveParams;
import de.flexiprovider.ec.parameters.CurveRegistry.BrainpoolP160r1;
import de.flexiprovider.pki.PKCS8EncodedKeySpec;
import de.flexiprovider.pki.X509EncodedKeySpec;
...
  Security.addProvider(new FlexiCoreProvider());
  Security.addProvider(new FlexiECProvider());

  KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECIES","FlexiEC");

  CurveParams ecParams = new BrainpoolP160r1();

  kpg.initialize(ecParams, new SecureRandom());
  KeyPair keyPair = kpg.generateKeyPair();

  PublicKey pubKey = keyPair.getPublic();
  byte[] encod_pubK = pubKey.getEncoded();

  String publicKey = Base64.encodeBytes(encod_pubK);
  System.out.println("Public Key :" +publikKey);

  PrivateKey privKey = keyPair.getPrivate();
  byte[] encod_privK = privKey.getEncoded();
  String privateKey = Base64.encodeBytes(encod_privK);
  System.out.println("Private Key :" +privateKey);

从上面的代码中,我将存储字符串“privateKey”和“publicKey”。现在我要加密消息。

  • 发送方
import (same as code above)
...
  Security.addProvider(new FlexiCoreProvider());
  Security.addProvider(new FlexiECProvider());
  Cipher cipher = Cipher.getInstance("ECIES","FlexiEC");
  IESParameterSpec iesParams = new IESParameterSpec ("AES128_CBC","HmacSHA1", null, null);

  byte[] decodedPubKey = Base64.decode(publicKey);

  X509EncodedKeySpec formatted_public = new X509EncodedKeySpec(decodedPubKey);
  KeyFactory kf = KeyFactory.getInstance("ECIES","FlexiEC");

  PublicKey publicKey = kf.generatePublic(formatted_public); // <--- I got error when hit this row

  cipher.init(Cipher.ENCRYPT_MODE, publicKey, iesParams);

  byte[] block = "this my message".getBytes();
  System.out.println("Plaintext: "+ new String(block));

  byte [] Ciphered = cipher.doFinal(block);
  System.out.println("Ciphertext : "+ Base64.encodeBytes(Ciphered));

来自上述发件人代码的错误是:

Exception in thread "main" de.flexiprovider.api.exceptions.InvalidKeySpecException:     java.lang.RuntimeException: java.security.InvalidAlgorithmParameterException: Caught IOException("Unknown named curve: 1.3.36.3.3.2.8.1.1.1")
at de.flexiprovider.ec.keys.ECKeyFactory.generatePublic(ECKeyFactory.java:205)
at de.flexiprovider.api.keys.KeyFactory.engineGeneratePublic(KeyFactory.java:39)
at java.security.KeyFactory.generatePublic(KeyFactory.java:328)

如何使用该命名曲线生成该公钥: 1.3.36.3.3.2.8.1.1.1 ?

  • 接收方(仅供参考)

如果发件人已成功加密邮件,现在我要解密邮件,这是我的代码(但不确定它是否像上面的发件人代码那样运行时没有错误):

 byte[] decodedPrivateKey = Base64.decode(privateKey);
 PKCS8EncodedKeySpec formatted_private = new PKCS8EncodedKeySpec(decodedPrivateKey);

 cipher.init(Cipher.DECRYPT_MODE, privKey, iesParams);
 byte[] decryptedCipher = cipher.doFinal(Ciphered);
 System.out.println("Decrypted message : "+ new String (decryptedCipher));

【问题讨论】:

  • 在此link 之后,我可以找到以“brainpoolP160r1”命名的“1.3.36.3.3.2.8.1.1.1”或 160 位曲线,但为什么错误说(“未知命名曲线:1.3.36.3 .3.2.8.1.1.1") ?我正在为我的 jdk-8 添加 jce 8,但仍然遇到这个问题

标签: java cryptography encryption-asymmetric


【解决方案1】:

由于我上面的代码存在未解决的错误,因为我认为这个 flexiprovider 与 jdk-8 不兼容,其中错误位于“KeyFactory kf = KeyFactory.getInstance("ECIES","FlexiEC")" 行中可以' t 找到该命名曲线,我更改并决定使用 BouncyCastle 提供程序进行 EC 加密(ECIES)并且它可以工作。但是我又想到了一个问题,正如我在 Flexiprovider 中看到的那样,它使用 ("AES128_CBC","HmacSHA1", null, null); 作为 IESParameterSpec强>。 但是对于 bouncycastle 提供者,我找不到使用 AES128_CBC 作为 iesparameterspec 的 IESParameterSpec 在哪里,如果我想在使用这个有弹性的提供者时将 iesparam 更改为 AES128_CBC,我该怎么做? 有人请解释一下 bouncy provider 中的这个 iesparam 规范,我对此很陌生。

这是我的信息代码:

  • 密钥对生成器类
import codec.Base64; // or whatever which can use to base64 encoding
import static java.lang.System.out;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

...

   Security.addProvider(new BouncyCastleProvider());

   KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECIES", "BC");
   ECGenParameterSpec brainpoolP160R1 = new ECGenParameterSpec("brainpoolP160R1");

   // I'm Still using this 160 bit GF(*p*) to keep the algorithm running fast rather than 256 or above 
   kpg.initialize(brainpoolP160R1);

   KeyPair kp = kpg.generateKeyPair();

   PublicKey publicKey = kp.getPublic();
   PrivateKey privateKey = kp.getPrivate();

   byte[] PublicKey = publicKey.getEncoded();
   byte[] PrivateKey = privateKey.getEncoded();

   out.println("Encoded Public : "+Base64.encode(PublicKey));
   out.println("\nEncoded Private : "+Base64.encode(PrivateKey));
...
  • 加密类(发送方)
import codec.Base64;
import codec.CorruptedCodeException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
    Security.addProvider(new BouncyCastleProvider());

// Assume that we know the encoded public key then return it by decode the public key
    byte[] decodedPublic = Base64.decode("MEIwFAYHKoZIzj0CAQYJKyQDAwIIAQEBAyoABNXclcmtUt8/rlGN47pc8ZpxkWgNgtKeeHdsVD0kIWLUMEULnchGZPA=".getBytes());

    X509EncodedKeySpec formatted_public = new X509EncodedKeySpec(decodedPublic);
    KeyFactory kf = KeyFactory.getInstance("EC","BC");
    PublicKey pubKey = kf.generatePublic(formatted_public);

    Cipher c = Cipher.getInstance("ECIES", "BC");

    c.init(Cipher.ENCRYPT_MODE, pubKey); // How can i put the AES128_CBC for ies parameter ? is that possible

    byte[] cipher = c.doFinal("This is the message".getBytes());
    System.out.println("Ciphertext : "+ Base64.encode(cipher));
...
  • 解密类(接收方)
import codec.Base64;
import codec.CorruptedCodeException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
    Security.addProvider(new BouncyCastleProvider());
// Assume that we know the encoded private key
    byte[] decodedPrivate = Base64.decode("MHECAQAwFAYHKoZIzj0CAQYJKyQDAwIIAQEBBFYwVAIBAQQUQmA9ifs472gNHBc5NSGYq56TlOKgCwYJKyQDAwIIAQEBoSwDKgAE1dyVya1S3z+uUY3julzxmnGRaA2C0p54d2xUPSQhYtQwRQudyEZk8A==".getBytes());

    PKCS8EncodedKeySpec formatted_private = new PKCS8EncodedKeySpec(decodedPrivate);
    KeyFactory kf = KeyFactory.getInstance("EC", "BC");
    PrivateKey privKey = kf.generatePrivate(formatted_private);

    Cipher c = Cipher.getInstance("ECIES");
    c.init(Cipher.DECRYPT_MODE, privKey); //How can i adding the **AES128_CBC** ies param ?

// Assume that we know the encoded cipher text
    byte[] plaintext = c.doFinal(Base64.decode("BKbCsKY7gDPld+F4jauQXvKSayYCt6vOjIGbsyXo5fHWo4Ax+Nt5BQ5FlkAGksFNRQ46agzfxjfuoxWkVfnt4gReDmpPYueUbiRiHp1Gwp0="));
    System.out.println("\nPlaintext : "+ new String (plaintext));
...

任何帮助都会得到帮助!

【讨论】:

  • 现在我得到了答案,我只是这样做Cipher.getInstance("ECIESWithAES/DHAES/NoPadding", "BC"); 只是阅读有关标准算法名称的文档。
  • 加密代码对您有用吗?我在 javax.crypto.Cipher.init(Cipher.java:1209) 的 javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011) 线程“main”中遇到异常 java.security.InvalidKeyException: Illegal key size or default parameters ) 在 javax.crypto.Cipher.init(Cipher.java:1153) 在 FlexiEC.main(FlexiEC.java:40)
  • @DovakinSkyrim 您是否尝试使用谷歌搜索该异常?您可能会错过有关库标准算法的密钥的一些内容。
猜你喜欢
  • 2013-05-15
  • 1970-01-01
  • 1970-01-01
  • 2012-08-30
  • 2014-10-24
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多