【问题标题】:Encrypt data in iOS with ECC, and decrypt data in java, failed用ECC加密iOS中的数据,用java解密数据,失败
【发布时间】:2021-04-18 07:06:28
【问题描述】:

我打算在iOS和Android用ECC加密,在server端解密。iOS用objective-C,Android和Server用Java。iOS用CryptopECChttps://github.com/SandeepAggarwal/CryptoppECC,加解密都能成功。服务器也可以使用Java成功加解密。但是,当我在服务器上解密IOS的加密数据时,它会失败。 iOS:

- (void)eccCryptForShortKey{
    NSString *publicKey = @"AvWy7WANZcn0ea1Li2AJCjo=";
    NSString *privateKey = @"ANqNuiMahQziTilCGa2bA3A=";
    NSString *str = @"hello world";

   CurveType curveType = CurveType_secp128r1;
   CryptoppECC *ecc = [[CryptoppECC alloc] init];
   // encrypt
   NSString *enStr =[ecc encrypt:str :publicKey curve:curveType];
   // decrypt
   NSString*deStr = [ecc decrypt:enStr :privateKey curve:curveType];
   if (deStr.length == 0) {
      NSLog(@"\n===Fail");
   }else{
      NSLog(@"\n===Succ: %@",deStr);
   }
}

Java:

public class EccCryptopp{
    public static final String curve = "secp128r1";
    private static final String CIPHER = "ECIES";
    private static final String ALGRITHM = "ECDSA";
    private static final String PROVIDER = "BC";
    private static final String publicKeyStrShort = "AvWy7WANZcn0ea1Li2AJCjo=";
    private static final String privateKeyStrShort = "ANqNuiMahQziTilCGa2bA3A=";
    static{
       Security.insertProviderAt(new BouncyCastleProvider(), 1);
    }
    public static void test() {
       //the data encrypted in iOS
      String encryptData = "BO1QGnFjDNVQ3rmcVhKJDZuYJl427Pbgt2lv9PvQ3ifXwDjKG/XcdqG5Mu1FEVahifhyXrtQEgvDUP1T0kjk0w==";
      String decryptData = decryptDataWithShortKey(encryptData, privateKeyStrShort);
      int dLength = decryptData.length();
      if (dLength == 0) {
        System.out.println("decrypt fail");
      } else {
        System.out.println("decrypt data:" + dLength);
        System.out.println(decryptData);
      }
   }

private static byte[] base64Decode(String s){
   return Base64.getDecoder().decode(s);
}

public static PublicKey loadPublicKeyWithShort(String curve, byte[] data)
    throws GeneralSecurityException {
   KeyFactory factory = KeyFactory.getInstance(ALGRITHM, PROVIDER);

   ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curve);
   ECCurve eccCurve = spec.getCurve();
   EllipticCurve ellipticCurve = EC5Util.convertCurve(eccCurve, spec.getSeed());
   java.security.spec.ECPoint point = ECPointUtil.decodePoint(ellipticCurve, data);
   java.security.spec.ECParameterSpec params = EC5Util.convertSpec(ellipticCurve, spec);
   ECPublicKeySpec keySpec = new ECPublicKeySpec(point, params);
   return factory.generatePublic(keySpec);
}

 public static PrivateKey loadPrivateKeyWithShort(String curve, byte[] data)
    throws  GeneralSecurityException {
    KeyFactory factory = KeyFactory.getInstance(ALGRITHM, PROVIDER);

    ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curve);
    ECCurve eccCurve = spec.getCurve();
    EllipticCurve ellipticCurve = EC5Util.convertCurve(eccCurve, spec.getSeed());
    java.security.spec.ECParameterSpec params = EC5Util.convertSpec(ellipticCurve, spec);
    ECPrivateKeySpec keySpec = new ECPrivateKeySpec(new BigInteger(1, data), params);
    return factory.generatePrivate(keySpec);
 }


 public static String encryptDataWithShortKey(String token, String publicKeyShort) {
    try {
       PublicKey publicKey = loadPublicKeyWithShort(curve, base64Decode(publicKeyShort));
       Cipher c = Cipher.getInstance(CIPHER);
       c.init(Cipher.ENCRYPT_MODE, publicKey);
       String messageString = token;
       byte[] message = messageString.getBytes();
       byte[] cipher = c.doFinal(message);
       return Base64.getEncoder().encodeToString(cipher);
    } catch (Exception e) {
       e.printStackTrace();
    }
   return null;
 }
public static String decryptDataWithShortKey(String message,String private_key) {
    try {
        PrivateKey privateKey = loadPrivateKeyWithShort(curve, base64Decode(private_key));

        Cipher c = Cipher.getInstance(CIPHER);
        byte[] token = ((Base64.getDecoder().decode(message.getBytes())));
        c.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] plaintext = c.doFinal(token);

        return new String(plaintext);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
}

<dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk15on</artifactId>
      <version>1.58</version>
</dependency>

获取IOS的加密内容并解密时,总是异常。 enter image description here

org.bouncycastle.jcajce.provider.util.BadBlockException: unable to process block
    at org.bouncycastle.jcajce.provider.asymmetric.ec.IESCipher.engineDoFinal(Unknown Source)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2207)
    at com.nonce.crypto.ecc.EccCryptopp.decryptDataWithShortKey(EccCryptopp.java:165)
    at com.nonce.crypto.ecc.EccCryptopp.test(EccCryptopp.java:59)
    at com.nonce.crypto.ecc.ECC.testEccCryptopp(ECC.java:38)
    at com.nonce.crypto.ecc.ECC.main(ECC.java:23)
Caused by: org.bouncycastle.crypto.InvalidCipherTextException: invalid MAC
    at org.bouncycastle.crypto.engines.IESEngine.decryptBlock(Unknown Source)
    at org.bouncycastle.crypto.engines.IESEngine.processBlock(Unknown Source)
    ... 6 more

不知道是Java解密还是IOS加密。

【问题讨论】:

    标签: java ios


    【解决方案1】:

    此问题不仅限于系统间操作。我在 java 平台上看到不同版本的充气城堡之间存在相同的问题。具体

    • bcprov 版本 1.52 和
    • bcprov 1.68 版

    椭圆曲线实现的两个版本之间似乎发生了一些变化。我仍在深入挖掘。

    【讨论】:

      【解决方案2】:

      所以我找到了我的问题的答案,也可能是你的。 BouncyCastle 在 1.52 和 1.53 之间更改了 ECIES 实现:

      ECIES/IES 只使用 4 字节标签长度作为 MAC 标签,而它本应是 8 字节标签。此问题现已修复,并添加了 OldECIES/OldIES 以实现向后兼容性。

      查看https://www.bouncycastle.org/releasenotes.html

      因此,您很可能正在尝试使用不同的实现(=版本)进行加密/解密。

      【讨论】:

        猜你喜欢
        • 2016-02-08
        • 1970-01-01
        • 2011-04-23
        • 2013-09-18
        • 1970-01-01
        • 1970-01-01
        • 2011-03-06
        • 2013-10-28
        • 2019-12-01
        相关资源
        最近更新 更多