为ruby获得这个“rsa/ecb/oaepwithsha-256和mgf1padding”组合

klh5stk1  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(555)

我有一个用于加密和解密的java代码,我想将其更改/转换为ruby代码。我在opensslgem中查找了一下,但发现ruby中提供了“rsa/ecb/oaepithha-256和mgf1padding”组合。如何实施?

public class EncryptDecryptService {

    public String encryptRequestObject(RequestObject requestObject) throws UnsupportedEncodingException, FileNotFoundException, CertificateException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
        PublicKey publicKey = getPublicKey(requestObject.getKeyFilename());
        byte[] message = requestObject.getString().getBytes("UTF-8");
        byte[] secret = encrypt(publicKey, message);
        return Base64.encodeBase64String(secret);
    }

    public String decryptRequestObject(RequestObject requestObject) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
        PrivateKey privateKey = getPrivateKey(requestObject.getKeyFilename(), requestObject.getKeyPassword());
        byte[] cipherText = Base64.decodeBase64(requestObject.getString());
        byte[] decrypted = decrypt(privateKey, cipherText);
        return new String(decrypted, "UTF-8");
    }

    private PublicKey getPublicKey(String filename) throws FileNotFoundException, CertificateException {
        FileInputStream fin = new FileInputStream(filename);
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        X509Certificate certificate = (X509Certificate) factory.generateCertificate(fin);
        PublicKey publicKey = certificate.getPublicKey();
        return publicKey;
    }

    private PrivateKey getPrivateKey(String filename, String password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException {
        FileInputStream fin = new FileInputStream(filename);
        KeyStore ks = KeyStore.getInstance("pkcs12");
        ks.load(fin, password.toCharArray());
        String str = ks.aliases().nextElement();
        PrivateKey privateKey = (PrivateKey) ks.getKey(str, password.toCharArray());
        return privateKey;
    }

    private byte[] encrypt(PublicKey key, byte[] plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(plainText);
    }

    private byte[] decrypt(PrivateKey key, byte[] cipherText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(cipherText);
    }
}
42fyovps

42fyovps1#

oaep使用多个参数,包括两个摘要,一个用于oaep(即,对oaep标签进行散列),另一个用于掩码生成函数(mgf1),请参阅rfc8017,第节。7.1.
标识符 RSA/ECB/OAEPWithSHA-256AndMGF1Padding 不明确,取决于提供程序。例如,sunjce提供程序使用sha-256作为oaep摘要,sha-1作为mgf1摘要,bouncycastle提供程序使用sha-256作为这两个摘要。
下面是一个用java代码加密和用ruby代码解密的例子(相反的方向是模拟的)。
在java端,sunjce提供程序用于wlog,并确定了涉及的摘要:

String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNvs/qUMjkfq2E9o0qn03+KJE7" + 
                "ASczEbn6q+kkthNBdmTsskikWsykpDPnLWhAVkmjz4alQyqw+mHYP9xhx8qUC4A3" + 
                "tXY0ObxANUUKhUvR7zNj4vk4t8F2nP3erWvaG8J+sN3Ubr40ZYIYLS6UHYRFrqRD" + 
                "CDhUtyjwERlz8KhLyQIDAQAB";

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(pubKey));
RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);

byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(StandardCharsets.UTF_8);
byte[] ciphertext = encrypt(publicKey, plaintext);

System.out.println("Ciphertext: " + Base64.getEncoder().encodeToString(ciphertext));

具有

private static byte[] encrypt(PublicKey key, byte[] plainText) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, key);
    OAEPParameterSpec oaepParameterSpec = cipher.getParameters().getParameterSpec(OAEPParameterSpec.class);
    MGF1ParameterSpec mgf1ParameterSpec = (MGF1ParameterSpec)oaepParameterSpec.getMGFParameters();
    System.out.println("Provider  : " + cipher.getProvider().getName());
    System.out.println("OAEP-Hash : " + oaepParameterSpec.getDigestAlgorithm());
    System.out.println("MGF1-Hash : " + mgf1ParameterSpec.getDigestAlgorithm());
    return cipher.doFinal(plainText);
}

对应于发布的 encrypt() 方法(附加输出除外)。代码产生(例如)以下输出:

Provider  : SunJCE
OAEP-Hash : SHA-256
MGF1-Hash : SHA-1
Ciphertext: WlozD9ojNRQafip41dpuuhBMe7ruH2FBWnMhbAaSuAtPDpHOUyKaAm6mO15BbvL3eTXyqfEQx29dYPJEbUr5T/WXs846PQN6g7Yv25EXGVbPCzc4aIbms76C1jP92wXNEGWMnu624Fq5W9MVXX75mfaY0Fjvrh5k/TFuO4AIxMk=

为完整起见,应提及的是,参数的明确说明也可用于:

Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); 
OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSource.PSpecified.DEFAULT);
cipher.init(Cipher.ENCRYPT_MODE, key, oaepParameterSpec);

因此,由于上面描述的矛盾,这个明确的规范是更健壮的替代方案。
在确定了摘要之后(因为提供者是已知的或者上面的输出是显式的),就可以进行ruby实现了。
ruby的一个可能的oaep实现是openssloaep。
这样,用于解密的ruby代码可以实现如下:

require 'openssl'
require 'openssl/oaep'
require 'base64'

private_key = 
'-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM2+z+pQyOR+rYT2
jSqfTf4okTsBJzMRufqr6SS2E0F2ZOyySKRazKSkM+ctaEBWSaPPhqVDKrD6Ydg/
3GHHypQLgDe1djQ5vEA1RQqFS9HvM2Pi+Ti3wXac/d6ta9obwn6w3dRuvjRlghgt
LpQdhEWupEMIOFS3KPARGXPwqEvJAgMBAAECgYADxGqqL7B9/pPOy3TqQuB6tuNx
4SOGm9x76onqUisoF7LhYqJR4Be/LAKHSR2PkATpKvOcMw6lDvCbtQ+j+rSK2PkN
4iDi1RYqbLUbZBS8vhrgU0CPlmgSSp1NBsqMK9265CaJox3frxmBK1yuf22RboIK
pqOzcluuA4aqLegmwQJBAP0+gM/tePzx+53DrxpYQvlfi9UJo7KeqIFL8TjMziKt
EaRGeOZ6UX/r6CQHojYKnNti7pjAwonsdwCTcv1yy7sCQQDP+/ww49VFHErON/MO
w5iYCsrM5Lx+Yc2JAjetCDpkMrRT92cgQ0nxR5+jNeh+gE2AmB9iKlNxsHJoRaPQ
lBRLAkEAl9hiZEp/wStXM8GhvKovfldMAPFGtlNrthtTCDvFXgVoDpgy5f9x3sIU
74WkPcMfSmyHpA/wlcKzmCTRTicHAQJBALUjq7MQ2tAEIgqUo/W52I6i55mnpZsU
pyOqcL8cqW5W0sNGd+SbdizTym8lJkX2jIlw8/RVFLOxjxLNhCzGqx0CQQDeUMnw
7KGP3F7BnbsXCp64YDdihzSO5X/Mfwxw6+S/pyKZ0/X4uwt24kZuoDnFzGWJYlea
sDQC6enIru+ne5es
-----END PRIVATE KEY-----'

key = OpenSSL::PKey::RSA.new(private_key) 
label = ''
md_oaep = OpenSSL::Digest::SHA256
md_mgf1 = OpenSSL::Digest::SHA1
cipher_text_B64 = 'WlozD9ojNRQafip41dpuuhBMe7ruH2FBWnMhbAaSuAtPDpHOUyKaAm6mO15BbvL3eTXyqfEQx29dYPJEbUr5T/WXs846PQN6g7Yv25EXGVbPCzc4aIbms76C1jP92wXNEGWMnu624Fq5W9MVXX75mfaY0Fjvrh5k/TFuO4AIxMk='
cipher_text = Base64.decode64(cipher_text_B64)
plain_text = key.private_decrypt_oaep(cipher_text, label, md_oaep, md_mgf1)
print(plain_text) # The quick brown fox jumps over the lazy dog

以原始明文作为输出。

相关问题