简体   繁体   English

获取 ruby 的“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”组合

[英]Get this “RSA/ECB/OAEPWithSHA-256AndMGF1Padding” combination for ruby

I have this java code for encryption and decryption, which I want to change/convert to Ruby code.我有这个 java 代码用于加密和解密,我想将其更改/转换为 Ruby 代码。 I looked up in OpenSSL gem but dint find the "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" combination available for ruby.我在 OpenSSL gem 中查找,但发现可用于 ruby 的“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”组合。 How do I implement it?我该如何实施?

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);
    }
}

OAEP uses several parameters, including two digests, one for OAEP (ie for hashing the OAEP label) and one for the mask generation function (MGF1), see RFC8017, sec. OAEP 使用多个参数,包括两个摘要,一个用于 OAEP(即,用于散列 OAEP 标签),一个用于掩码生成 function (MGF1),请参见RFC8017,sec. 7.1 . 7.1 .

The identifier RSA/ECB/OAEPWithSHA-256AndMGF1Padding is ambiguous and depends on the provider.标识符RSA/ECB/OAEPWithSHA-256AndMGF1Padding不明确,取决于提供者。 For example the SunJCE provider uses SHA-256 as OAEP digest and SHA-1 as MGF1 digest, the BouncyCastle provider uses SHA-256 for both digests.例如,SunJCE 提供程序使用 SHA-256 作为 OAEP 摘要和 SHA-1 作为 MGF1 摘要,BouncyCastle 提供程序使用 SHA-256 作为两种摘要。

The following is an example of the encryption with the Java code and the decryption with the Ruby code (the opposite direction is analog).下面是用Java码加密和用Ruby码解密的例子(反方向为模拟)。


On the Java side the SunJCE provider is used WLOG and the digests involved are determined:在 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));

with

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);
}

which corresponds to the posted encrypt() method (except for the additional output).这对应于发布的encrypt()方法(附加输出除外)。 The code produces (eg) the following output:该代码产生(例如)以下 output:

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

For completeness it should be mentioned that an explicit specification of the parameters is also possible with:为了完整起见,应该提到参数的显式规范也可以使用:

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);

whereby this explicit specification is the more robust alternative because of the ambivalence described above.由于上面描述的矛盾,这个明确的规范是更稳健的选择。


After the digests have been determined (either because the provider is known or explicitly with the above output) a Ruby implementation can be made.在确定摘要后(因为提供者是已知的或通过上述输出明确),可以进行 Ruby 实现。

A possible OAEP implementation for Ruby is openssl-oaep . Ruby 的一个可能的 OAEP 实现是openssl-oaep

With this, the Ruby code for decryption can be implemented as follows:有了这个,用于解密的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

with the original plaintext as output.原始明文为 output。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 分解 RSA/ECB/OAEPWithSHA-256AndMGF1Padding - Breaking down RSA/ECB/OAEPWithSHA-256AndMGF1Padding Java RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING 迁移到 Go - Java RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING Migrate To Go “RSA/ECB/OAEPWITHSHA256ANDMGF1PADDING”和“RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING”之间的区别是什么 - what is deference between "RSA/ECB/OAEPWITHSHA256ANDMGF1PADDING" and "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING" C# Bouncy Castle 中的 RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING - 对于 RSA 密码输入太大 - RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING in C# Bouncy Castle - input too large for RSA cipher Java的RSA / ECB / OAEPWITHSHA-256ANDMGF1PADDING在PHP中等效 - Java's RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING equivalent in PHP RSA / ECB / OAEPWithSHA-256AndMGF1Padding但MGF1使用SHA-256? - RSA/ECB/OAEPWithSHA-256AndMGF1Padding but with MGF1 using SHA-256? 错误的填充例外-pkcs11中的RSA / ECB / OAEPWITHSHA-256ANDMGF1PADDING - Bad Padding Exception - RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING in pkcs11 C#等效于Java RSA / ECB / OAEPWithSHA-256AndMGF1Padding - C# equivalent to Java RSA/ECB/OAEPWithSHA-256AndMGF1Padding Java 的 RSA/ECB/OAEPWithSHA-256AndMGF1Padding 在 Node.js 中的等价物 - Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding equivalent in Node.js java RSA/ECB/OAEPWithSHA 256AndMGF1Padding 在 golang 中等效 - java RSA/ECB/OAEPWithSHA 256AndMGF1Padding equivalent in golang
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM