Java:OpenSSLRSAPrivateCrtKey 与 OpenSSLRSAPrivateKey

DH2*_*H28 5 java android rsa

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

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
PrivateKey privateKey = kp.getPrivate();
Run Code Online (Sandbox Code Playgroud)

我得到了 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);
Run Code Online (Sandbox Code Playgroud)

但是这次我得到了 OpenSSLRSAPrivateKey 表示。

我想知道OpenSSLRSAPrivateCrtKey和之间有什么区别OpenSSLRSAPrivateKey。另外,我应该使用 PrivateKey 的哪种表示来解密由该密钥对中的公钥加密的信息?

Laj*_*pad 1

OpenSSLRSAPrivateCrtKey extends OpenSSLRSAPrivateKey

新成员

private BigInteger publicExponent;

private BigInteger primeP;

private BigInteger primeQ;

private BigInteger primeExponentP;

private BigInteger primeExponentQ;

private BigInteger crtCoefficient;
Run Code Online (Sandbox Code Playgroud)

新的构造函数,调用 init

OpenSSLRSAPrivateCrtKey(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException {
    super(init(rsaKeySpec));
}
Run Code Online (Sandbox Code Playgroud)

初始化覆盖

最初是

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在它是

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,当OpenSSLKey实例化时,我们NativeCrypto.EVP_PKEY_new_RSA在这两种情况下都通过了。OpenSSLRSAPrivateCrtKey 通过:

  • 公共指数
  • 素P
  • 素Q
  • 素数指数P
  • 素数指数Q
  • 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);
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

新版本计算

  • 模数
  • 私人指数

如果失败,则会抛出一些异常。否则,它会继续计算内容,即:

  • 公共指数
  • 素P
  • 素Q
  • 素数指数P
  • 素数指数Q
  • 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]);
    }
}
Run Code Online (Sandbox Code Playgroud)

@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]);
    }
}
Run Code Online (Sandbox Code Playgroud)

因为新成员的加入

吸气剂

@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;
}
Run Code Online (Sandbox Code Playgroud)

等于

已更改为

@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;
}
Run Code Online (Sandbox Code Playgroud)

@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;
}
Run Code Online (Sandbox Code Playgroud)

因为有新成员。

哈希码

@Override
public final int hashCode() {
    int hashCode = super.hashCode();
    if (publicExponent != null) {
        hashCode ^= publicExponent.hashCode();
    }
    return hashCode;
}
Run Code Online (Sandbox Code Playgroud)

如果 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();
}
Run Code Online (Sandbox Code Playgroud)

@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();
}
Run Code Online (Sandbox Code Playgroud)

读取对象

更改自

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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

写对象

更改自

private void writeObject(ObjectOutputStream stream) throws IOException {
    if (key.isHardwareBacked()) {
        throw new NotSerializableException("Hardware backed keys can not be serialized");
    }
    ensureReadParams();
    stream.defaultWriteObject();
}
Run Code Online (Sandbox Code Playgroud)

private void writeObject(ObjectOutputStream stream) throws IOException {
    if (getOpenSSLKey().isHardwareBacked()) {
        throw new NotSerializableException("Hardware backed keys cannot be serialized");
    }

    ensureReadParams();
    stream.defaultWriteObject();
}
Run Code Online (Sandbox Code Playgroud)