Java:OpenSSLRSAPrivateCrtKey 与 OpenSSLRSAPrivateKey

标签 java android rsa

当我使用以下代码生成私钥时

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
PrivateKey privateKey = kp.getPrivate();
我得到 PrivateKey 的 OpenSSLRSAPrivateCrtKey 表示。
然后我把它变成字节数组,保存然后使用这段代码恢复:
byte[] encodedPrivateKey = null;
fileInputStream = new FileInputStream(file);
encodedPrivateKey = new byte[(int) file.length()];
fileInputStream.read(encodedPrivateKey);
fileInputStream.close();

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
但是这次我得到了 OpenSSLRSAPrivateKey 表示。
我想知道 OpenSSLRSAPrivateCrtKey 和有什么区别和 OpenSSLRSAPrivateKey .另外,我应该使用哪种 PrivateKey 表示来解密由该 key 对中的公钥加密的信息?

最佳答案

OpenSSLRSAPrivateCrtKey extends OpenSSLRSAPrivateKey .
新成员

private BigInteger publicExponent;

private BigInteger primeP;

private BigInteger primeQ;

private BigInteger primeExponentP;

private BigInteger primeExponentQ;

private BigInteger crtCoefficient;
新的构造函数,调用 init
OpenSSLRSAPrivateCrtKey(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException {
    super(init(rsaKeySpec));
}
初始化覆盖
最初是
private static OpenSSLKey init(RSAPrivateKeySpec rsaKeySpec) throws InvalidKeySpecException {
    final BigInteger modulus = rsaKeySpec.getModulus();
    final BigInteger privateExponent = rsaKeySpec.getPrivateExponent();

    if (modulus == null) {
        throw new InvalidKeySpecException("modulus == null");
    } else if (privateExponent == null) {
        throw new InvalidKeySpecException("privateExponent == null");
    }

    try {
        return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA(
                modulus.toByteArray(),
                null,
                privateExponent.toByteArray(),
                null,
                null,
                null,
                null,
                null));
    } catch (Exception e) {
        throw new InvalidKeySpecException(e);
    }
}
现在它是
private static OpenSSLKey init(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException {
    BigInteger modulus = rsaKeySpec.getModulus();
    BigInteger privateExponent = rsaKeySpec.getPrivateExponent();

    if (modulus == null) {
        throw new InvalidKeySpecException("modulus == null");
    } else if (privateExponent == null) {
        throw new InvalidKeySpecException("privateExponent == null");
    }

    try {
        /*
         * OpenSSL uses the public modulus to do RSA blinding. If
         * the public modulus is not available, the call to
         * EVP_PKEY_new_RSA will turn off blinding for this key
         * instance.
         */
        final BigInteger publicExponent = rsaKeySpec.getPublicExponent();
        final BigInteger primeP = rsaKeySpec.getPrimeP();
        final BigInteger primeQ = rsaKeySpec.getPrimeQ();
        final BigInteger primeExponentP = rsaKeySpec.getPrimeExponentP();
        final BigInteger primeExponentQ = rsaKeySpec.getPrimeExponentQ();
        final BigInteger crtCoefficient = rsaKeySpec.getCrtCoefficient();

        return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA(
                modulus.toByteArray(),
                publicExponent == null ? null : publicExponent.toByteArray(),
                privateExponent.toByteArray(),
                primeP == null ? null : primeP.toByteArray(),
                primeQ == null ? null : primeQ.toByteArray(),
                primeExponentP == null ? null : primeExponentP.toByteArray(),
                primeExponentQ == null ? null : primeExponentQ.toByteArray(),
                crtCoefficient == null ? null : crtCoefficient.toByteArray()));
    } catch (Exception e) {
        throw new InvalidKeySpecException(e);
    }
}
正如我们所见,当 OpenSSLKey被实例化,我们通过 NativeCrypto.EVP_PKEY_new_RSA在这两种情况下。 OpenSSLRSAPrivateCrtKey 通过:
  • 公共(public)指数
  • 素数P
  • 素数
  • 素数指数P
  • primeExponentQ
  • crt系数

  • 获取实例
    它从
    static OpenSSLRSAPrivateKey getInstance(OpenSSLKey key) {
        byte[][] params = NativeCrypto.get_RSA_private_params(key.getNativeRef());
        if (params[1] != null) {
            return new OpenSSLRSAPrivateCrtKey(key, params);
        }
        return new OpenSSLRSAPrivateKey(key, params);
    }
    
    static OpenSSLKey getInstance(RSAPrivateCrtKey rsaPrivateKey) throws InvalidKeyException {
        /**
         * If the key is not encodable (PKCS11-like key), then wrap it and use
         * JNI upcalls to satisfy requests.
         */
        if (rsaPrivateKey.getFormat() == null) {
            return wrapPlatformKey(rsaPrivateKey);
        }
    
        BigInteger modulus = rsaPrivateKey.getModulus();
        BigInteger privateExponent = rsaPrivateKey.getPrivateExponent();
    
        if (modulus == null) {
            throw new InvalidKeyException("modulus == null");
        } else if (privateExponent == null) {
            throw new InvalidKeyException("privateExponent == null");
        }
    
        try {
            /*
             * OpenSSL uses the public modulus to do RSA blinding. If
             * the public modulus is not available, the call to
             * EVP_PKEY_new_RSA will turn off blinding for this key
             * instance.
             */
            final BigInteger publicExponent = rsaPrivateKey.getPublicExponent();
            final BigInteger primeP = rsaPrivateKey.getPrimeP();
            final BigInteger primeQ = rsaPrivateKey.getPrimeQ();
            final BigInteger primeExponentP = rsaPrivateKey.getPrimeExponentP();
            final BigInteger primeExponentQ = rsaPrivateKey.getPrimeExponentQ();
            final BigInteger crtCoefficient = rsaPrivateKey.getCrtCoefficient();
    
            return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA(
                    modulus.toByteArray(),
                    publicExponent == null ? null : publicExponent.toByteArray(),
                    privateExponent.toByteArray(),
                    primeP == null ? null : primeP.toByteArray(),
                    primeQ == null ? null : primeQ.toByteArray(),
                    primeExponentP == null ? null : primeExponentP.toByteArray(),
                    primeExponentQ == null ? null : primeExponentQ.toByteArray(),
                    crtCoefficient == null ? null : crtCoefficient.toByteArray()));
        } catch (Exception e) {
            throw new InvalidKeyException(e);
        }
    }
    
    新版本计算
  • 模数
  • 私有(private)指数

  • 如果失败,则会引发一些异常。否则,它会继续计算东西,即:
  • 公共(public)指数
  • 素数P
  • 素数
  • 素数指数P
  • primeExponentQ
  • crt系数

  • 然后生成 OpenSSLKey类似于 init .我认为这可以重构,因为它涉及一些代码重复,但我的意见不如差异重要。
    读取参数
    这从
    void readParams(byte[][] params) {
        if (params[0] == null) {
            throw new NullPointerException("modulus == null");
        } else if (params[2] == null && !key.isHardwareBacked()) {
            throw new NullPointerException("privateExponent == null");
        }
    
        modulus = new BigInteger(params[0]);
    
        // ENGINE-based keys are not guaranteed to have a private exponent.
        if (params[2] != null) {
            privateExponent = new BigInteger(params[2]);
        }
    }
    
    @Override
    synchronized void readParams(byte[][] params) {
        super.readParams(params);
        // params[0] read in super.readParams
        if (params[1] != null) {
            publicExponent = new BigInteger(params[1]);
        }
        // params[2] read in super.readParams
        if (params[3] != null) {
            primeP = new BigInteger(params[3]);
        }
        if (params[4] != null) {
            primeQ = new BigInteger(params[4]);
        }
        if (params[5] != null) {
            primeExponentP = new BigInteger(params[5]);
        }
        if (params[6] != null) {
            primeExponentQ = new BigInteger(params[6]);
        }
        if (params[7] != null) {
            crtCoefficient = new BigInteger(params[7]);
        }
    }
    
    因为新成员
    setter/getter
    @Override
    public BigInteger getPublicExponent() {
        ensureReadParams();
        return publicExponent;
    }
    
    @Override
    public BigInteger getPrimeP() {
        ensureReadParams();
        return primeP;
    }
    
    @Override
    public BigInteger getPrimeQ() {
        ensureReadParams();
        return primeQ;
    }
    
    @Override
    public BigInteger getPrimeExponentP() {
        ensureReadParams();
        return primeExponentP;
    }
    
    @Override
    public BigInteger getPrimeExponentQ() {
        ensureReadParams();
        return primeExponentQ;
    }
    
    @Override
    public BigInteger getCrtCoefficient() {
        ensureReadParams();
        return crtCoefficient;
    }
    
    等于
    已经从
    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
    
        if (o instanceof OpenSSLRSAPrivateKey) {
            OpenSSLRSAPrivateKey other = (OpenSSLRSAPrivateKey) o;
            return key.equals(other.getOpenSSLKey());
        }
    
        if (o instanceof RSAPrivateKey) {
            ensureReadParams();
            RSAPrivateKey other = (RSAPrivateKey) o;
    
            return modulus.equals(other.getModulus())
                    && privateExponent.equals(other.getPrivateExponent());
        }
    
        return false;
    }
    
    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
    
        if (o instanceof OpenSSLRSAPrivateKey) {
            OpenSSLRSAPrivateKey other = (OpenSSLRSAPrivateKey) o;
            return getOpenSSLKey().equals(other.getOpenSSLKey());
        }
    
        if (o instanceof RSAPrivateCrtKey) {
            ensureReadParams();
            RSAPrivateCrtKey other = (RSAPrivateCrtKey) o;
    
            if (getOpenSSLKey().isHardwareBacked()) {
                return getModulus().equals(other.getModulus())
                        && publicExponent.equals(other.getPublicExponent());
            } else {
                return getModulus().equals(other.getModulus())
                        && publicExponent.equals(other.getPublicExponent())
                        && getPrivateExponent().equals(other.getPrivateExponent())
                        && primeP.equals(other.getPrimeP()) && primeQ.equals(other.getPrimeQ())
                        && primeExponentP.equals(other.getPrimeExponentP())
                        && primeExponentQ.equals(other.getPrimeExponentQ())
                        && crtCoefficient.equals(other.getCrtCoefficient());
            }
        } else if (o instanceof RSAPrivateKey) {
            ensureReadParams();
            RSAPrivateKey other = (RSAPrivateKey) o;
    
            if (getOpenSSLKey().isHardwareBacked()) {
                return getModulus().equals(other.getModulus());
            } else {
                return getModulus().equals(other.getModulus())
                        && getPrivateExponent().equals(other.getPrivateExponent());
            }
        }
    
        return false;
    }
    
    因为新成员。
    哈希码
    @Override
    public final int hashCode() {
        int hashCode = super.hashCode();
        if (publicExponent != null) {
            hashCode ^= publicExponent.hashCode();
        }
        return hashCode;
    }
    
    如果 publicExponent 为 null,那么它与基类中的相同。如果不是,则根据基类的哈希码和 publicExponent 的哈希码计算 hashCode,计算两者之间的按位异或。
    到字符串
    从改变
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("OpenSSLRSAPrivateKey{");
    
        ensureReadParams();
        sb.append("modulus=");
        sb.append(modulus.toString(16));
    
        return sb.toString();
    }
    
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("OpenSSLRSAPrivateCrtKey{");
    
        ensureReadParams();
        sb.append("modulus=");
        sb.append(getModulus().toString(16));
    
        if (publicExponent != null) {
            sb.append(',');
            sb.append("publicExponent=");
            sb.append(publicExponent.toString(16));
        }
    
        sb.append('}');
        return sb.toString();
    }
    
    读取对象
    从改变
    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
    
        key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA(
                modulus.toByteArray(),
                null,
                privateExponent.toByteArray(),
                null,
                null,
                null,
                null,
                null));
        fetchedParams = true;
    }
    
    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
    
        key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA(
                modulus.toByteArray(),
                publicExponent == null ? null : publicExponent.toByteArray(),
                privateExponent.toByteArray(),
                primeP == null ? null : primeP.toByteArray(),
                primeQ == null ? null : primeQ.toByteArray(),
                primeExponentP == null ? null : primeExponentP.toByteArray(),
                primeExponentQ == null ? null : primeExponentQ.toByteArray(),
                crtCoefficient == null ? null : crtCoefficient.toByteArray()));
        fetchedParams = true;
    }
    
    写对象
    从改变
    private void writeObject(ObjectOutputStream stream) throws IOException {
        if (key.isHardwareBacked()) {
            throw new NotSerializableException("Hardware backed keys can not be serialized");
        }
        ensureReadParams();
        stream.defaultWriteObject();
    }
    
    private void writeObject(ObjectOutputStream stream) throws IOException {
        if (getOpenSSLKey().isHardwareBacked()) {
            throw new NotSerializableException("Hardware backed keys cannot be serialized");
        }
    
        ensureReadParams();
        stream.defaultWriteObject();
    }
    

    关于Java:OpenSSLRSAPrivateCrtKey 与 OpenSSLRSAPrivateKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35920464/

    相关文章:

    java - 使用监视文件夹重新启动线程

    java - 在 HashMap 中存储字符和二进制数

    android - ListView 列表选择器不工作

    java - 如何使用Material组件的Slider显示标签?

    c# - .NET 下的原始 RSA 加密(又名 ECB/NoPadding)?

    python - 如何从文件中将公共(public) RSA key 加载到 Python-RSA 中?

    java - 未处理的异常类型错误

    android - 环路效率比较

    .net - 使用 AES 加密文件,使用 RSA 加密 key - 我走在正确的轨道上吗?

    java - Spring - 请求的资源不可用