docs: private byte[] decrypt(byte[] in, int inOff, int inLen) {
  		// 获取曲线点
  		final byte[] c1 = new byte[this.curveLength * 2 + 1];
  		System.arraycopy(in, inOff, c1, 0, c1.length);
  
  		ECPoint c1P = this.ecParams.getCurve().decodePoint(c1);
  		if (c1P.multiply(this.ecParams.getH()).isInfinity()) {
  			throw new CryptoException("[h]C1 at infinity");
  		}
  		c1P = c1P.multiply(((ECPrivateKeyParameters) ecKey).getD()).normalize();
  
  		final int digestSize = this.digest.getDigestSize();
  
  		// 解密C2数据
  		final byte[] c2 = new byte[inLen - c1.length - digestSize];
  
  		if (SM2Mode.C1C3C2 == this.mode) {
  			// C2位于第三部分
  			System.arraycopy(in, inOff + c1.length + digestSize, c2, 0, c2.length);
  		} else {
  			// C2位于第二部分
  			System.arraycopy(in, inOff + c1.length, c2, 0, c2.length);
  		}
  		kdf(c1P, c2);
  
  		// 使用摘要验证C2数据
  		final byte[] c3 = new byte[digestSize];
  
  		addFieldElement(c1P.getAffineXCoord());
  		this.digest.update(c2, 0, c2.length);
  		addFieldElement(c1P.getAffineYCoord());
  		this.digest.doFinal(c3, 0);
  
  		int check = 0;
  		for (int i = 0; i != c3.length; i++) {
  			check |= c3[i] ^ in[inOff + c1.length + ((SM2Mode.C1C3C2 == this.mode) ? 0 : c2.length) + i];
  		}
  
  		Arrays.fill(c1, (byte) 0);
  		Arrays.fill(c3, (byte) 0);
  
  		if (check != 0) {
  			Arrays.fill(c2, (byte) 0);
  			throw new CryptoException("invalid cipher text");
  		}
  
  		return c2;
  	}