Java 为给定的模数和指数生成 RSA 密钥

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24546397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 12:51:17  来源:igfitidea点击:

Generating RSA keys for given modulus and exponent

javasecurityencryptionrsa

提问by vara

I have been asked to generate the RSA key using given modulusand exponentvalues. But I have idea only about generating the keys without specifying the modulus and exponent. Whatever the value I am given is seems to be big integer values. I searched about this in web and worked out some thing, But it could not went through success.

我被要求使用给定modulusexponent值生成 RSA 密钥。但我只知道生成密钥而不指定模数和指数。无论我得到什么值,似乎都是大整数值。我在网上搜索了这个并解决了一些问题,但它无法成功。

So if anybody has done this before, can they give me some hints please?

所以如果有人以前做过这个,他们能给我一些提示吗?

This is sample program we have tried with given values.

这是我们尝试使用给定值的示例程序。

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

public class Sample {
        public static void main( String args[] ) {

                BigInteger modulus  = new BigInteger("350871044328208704010580786055405681");
                BigInteger exponent = new BigInteger("545161406957801571");

                try {                    
                        RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
                        RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(modulus, exponent);

                        KeyFactory factory = KeyFactory.getInstance("RSA");

                        PublicKey pub = factory.generatePublic(spec);
                        PrivateKey priv = factory.generatePrivate(privateSpec); 

                        System.out.println("Public Key : "+ byteArrayToHexString( pub.getEncoded() ));
                        System.out.println("Private Key : "+ byteArrayToHexString( priv.getEncoded() ));
                }                        
                catch( Exception e ) {   
                        System.out.println(e.toString());       
                }                        
        }         
        public static String byteArrayToHexString(byte[] bytes)          
        {         
                StringBuffer buffer = new StringBuffer();
                for(int i=0; i<bytes.length; i++)
                {                        
                        if(((int)bytes[i] & 0xff) < 0x10)       
                                buffer.append("0");                               
                        buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
                }                        
                return buffer.toString();
        }         
}

ERROR:

错误:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: RSA keys must be at least 512 bits long

java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException:RSA 密钥的长度必须至少为 512 位

回答by albciff

I give you some information about RSA. First of all in RSA keys the modulus = p·qwhere pand qare distinct prime numbers, the modulus length it's the key length. So when you are receiving the exception:

我给你一些关于 RSA 的信息。首先,在 RSA 密钥中,modulus = p·qwherepq是不同的素数,模数长度是key length. 因此,当您收到异常时:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: RSA keys must be at least 512 bits long

java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException:RSA 密钥的长度必须至少为 512 位

This means that your modulus at least must be 512 bits long.

这意味着您的模数至少必须为 512 位长。

Besides in your code there is also another error, you're using the same exponent for public and private key, but this exponents must be different numbers.

除了在您的代码中还有另一个错误,您对公钥和私钥使用相同的指数,但该指数必须是不同的数字。

In resume you have to calculate the modulus, public exponent and private exponent with java.math.BigIntegerfollowing the RSA key generation algorithm to generate a correct keys. I give you an example from your code:

在简历中,您必须java.math.BigInteger按照 RSA 密钥生成算法计算模数、公共指数和私人指数以生成正确的密钥。我从你的代码中给你一个例子:

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

public class Sample {
    public static void main( String args[] ) {

        int keySize = 512;  
        SecureRandom random = new SecureRandom();
        // Choose two distinct prime numbers p and q.
        BigInteger p = BigInteger.probablePrime(keySize/2,random);
        BigInteger q = BigInteger.probablePrime(keySize/2,random);
        // Compute n = pq (modulus)
        BigInteger modulus = p.multiply(q);
        // Compute φ(n) = φ(p)φ(q) = (p ? 1)(q ? 1) = n - (p + q -1), where φ is Euler's totient function.
        // and choose an integer e such that 1 < e < φ(n) and gcd(e, φ(n)) = 1; i.e., e and φ(n) are coprime.
        BigInteger m = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
        BigInteger publicExponent = getCoprime(m,random);
        // Determine d as d ≡ e?1 (mod φ(n)); i.e., d is the multiplicative inverse of e (modulo φ(n)).
        BigInteger privateExponent = publicExponent.modInverse(m);


        try {                    
            RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent);
            RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(modulus, privateExponent);

            KeyFactory factory = KeyFactory.getInstance("RSA");

            PublicKey pub = factory.generatePublic(spec);
            PrivateKey priv = factory.generatePrivate(privateSpec); 

            System.out.println("Public Key : "+ byteArrayToHexString( pub.getEncoded() ));
            System.out.println("Private Key : "+ byteArrayToHexString( priv.getEncoded() ));
        }                        
        catch( Exception e ) {   
            System.out.println(e.toString());       
        }                        
    }         

    public static BigInteger getCoprime(BigInteger m, SecureRandom random) {
        int length = m.bitLength()-1;
        BigInteger e = BigInteger.probablePrime(length,random);
        while (! (m.gcd(e)).equals(BigInteger.ONE) ) {
            e = BigInteger.probablePrime(length,random);
        }
        return e;
    }


    public static String byteArrayToHexString(byte[] bytes)          
    {         
        StringBuffer buffer = new StringBuffer();
        for(int i=0; i<bytes.length; i++)
        {                        
            if(((int)bytes[i] & 0xff) < 0x10)       
                buffer.append("0");                               
            buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
        }                        
        return buffer.toString();
    }         
}

Hope this help,

希望这有帮助,