Public key cryptography is a well-known concept, but for some reason the JCE (Java Cryptography Extensions) documentation doesn't at all make it clear how to interoperate with common public key formats such as those produced by openssl. If you try to do a search on the web for how to make RSA public key cryptography work in Java, you quickly find a lot of people asking questions and not a lot of people answering them. In this post, I'm going to try to lay out very clearly how I got this working.
Just to set expectations, this is not a tutorial about how to use the cryptography APIs themselves in javax.crypto (look at the JCE tutorials from Sun for this); nor is this a primer about how public key cryptography works. This article is really about how to manage the keys with off-the-shelf utilities available to your friendly, neighborhood sysadmin and still make use of them from Java programs. Really, this boils down to "how do I get these darn keys loaded into a Java program where they can be used?" This is the article I wish I had when I started trying to muck around with this stuff....
Managing the keys
Openssl. This is the de-facto tool sysadmins use for managing public/private keys, X.509 certificates, etc. This is what we want to create/manage our keys with, so that they can be stored in formats that are common across most Un*x systems and utilities (like, say, C programs using the openssl library...). Java has this notion of its own keystore, and Sun will give you the keytool command with Java, but that doesn't do you much good outside of Java world.
Creating the keypair. We are going to create a keypair, saving it in openssl's preferred PEM format. PEM formats are ASCII and hence easy to email around as needed. However, we will need to save the keys in the binary DER format so Java can read them. Without further ado, here is the magical incantation for creating the keys we'll use:
# generate a 2048-bit RSA private key $ openssl genrsa -out private_key.pem 2048 # convert private Key to PKCS#8 format (so Java can read it) $ openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem \ -out private_key.der -nocrypt # output public key portion in DER format (so Java can read it) $ openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
You keep private_key.pem around for reference, but you hand the DER versions to your Java programs.
Loading the keys into Java
Really, this boils down to knowing what type of KeySpec to use when reading in the keys. To read in the private key:
import java.io.*; import java.security.*; import java.security.spec.*; public class PrivateKeyReader { public static PrivateKey get(String filename) throws Exception { File f = new File(filename); FileInputStream fis = new FileInputStream(f); DataInputStream dis = new DataInputStream(fis); byte[] keyBytes = new byte[(int)f.length()]; dis.readFully(keyBytes); dis.close(); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(spec); } }
And now, to read in the public key:
import java.io.*; import java.security.*; import java.security.spec.*; public class PublicKeyReader { public static PublicKey get(String filename) throws Exception { File f = new File(filename); FileInputStream fis = new FileInputStream(f); DataInputStream dis = new DataInputStream(fis); byte[] keyBytes = new byte[(int)f.length()]; dis.readFully(keyBytes); dis.close(); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePublic(spec); } }
That's about it. The hard part was figuring out a compatible set of:
- openssl DER output options (particularly the PKCS#8 encoding)
- which type of KeySpec Java needed to use (strangely enough, the public key needs the "X509" keyspec, even though you would normally handle X.509 certificates with the openssl x509 command, not the openssl rsa command. Real intuitive.)
From here, signing and verifying work as described in the JCE documentation; the only other thing you need to know is that you can use the "SHA1withRSA" algorithm when you get your java.security.Signature instance for signing/verifying, and that you want the "RSA" algorithm when you get your javax.crypto.Cipher instance for encrypting/decrypting.
Many happy security returns to you.
相关推荐
在《[2003]Certificateless Public Key Cryptography》这篇论文中,作者可能详细探讨了无证书公钥加密的理论基础,包括其安全性模型、密钥生成算法、加密和解密过程,以及可能的攻击场景和防御策略。论文还可能讨论...
string publicKey = rsa.ToXmlString(false); string privateKey = rsa.ToXmlString(true); // 存储或传输公钥和私钥(这里只是打印出来) Console.WriteLine("Public Key: " + publicKey); Console.WriteLine...
- 配备专用的公钥硬件加速器(Public Key Hardware Accelerator, PKHA)。 - 支持ECDSA签名生成与验证操作,以及椭圆曲线密钥对生成。 - 支持RSA加密解密操作及密钥对生成。 #### 黑键机制 黑键机制基于设备特定的...
#### 标题:公钥密码学(Public Key Cryptography) **公钥密码学**是一种加密技术,它基于一对密钥:公钥和私钥。这种加密方法在现代通信系统中发挥着至关重要的作用,尤其是在保障数据的安全性和隐私方面。 ####...
JAVA中,密钥通常以`java.security.KeyPair`或其组成部分(`PublicKey`和`PrivateKey`)的形式存储,而C#中则是`RSACryptoServiceProvider`对象。PHP中,密钥通常以PEM格式的字符串表示。在转换时,需要将这些对象或...
传统上,公钥密码系统的安全性依赖于大整数分解问题(如RSA)或离散对数问题(如Diffie-Hellman密钥交换),这些算法可能在未来的量子计算机面前变得脆弱。因此,研究人员正在探索新的公钥加密算法,这些算法能够...
Java的PublicKey和PrivateKey接口代表公钥和私钥,它们分别由RSAPublicKey和RSAPrivateKey实现。RSA加密通常与Cipher类结合使用,通过指定RSA算法来完成加解密过程。 6. 数字签名 在Java中,Signature类用于实现...
在Java中实现RSA加密解密,需要使用Java Cryptography Extension (JCE)库。以下是使用RSA加密解密的基本步骤: 1. **生成密钥对**:首先,我们需要生成一对公钥和私钥。在Java中,`java.security.KeyPairGenerator`...
工具类通常会提供便利的静态方法,如`encrypt(String plaintext, PublicKey publicKey)`和`decrypt(byte[] ciphertext, PrivateKey privateKey)`。 5. 使用场景: 在JSP应用中,RSA的常见应用场景包括登录认证、...
PublicKey publicKey = keyPair.getPublic(); // 获取公钥 byte[] encryptedBytes = publicKey.encrypt(data); // 假设encrypt()是使用公钥加密的方法 ``` 在C#端,你需要使用私钥来解密这些加密的字节。C#中处理...
2. **C#实现RSA**:在C#中,`System.Security.Cryptography.RSACryptoServiceProvider`类提供了RSA加密和解密的功能。你可以通过这个类创建、保存和加载密钥对,然后使用`Encrypt`和`Decrypt`方法进行加解密操作。 ...
PKCS #1(Public-Key Cryptography Standards #1)是RSA安全公司制定的一系列公开密钥加密标准之一,其中“PKCS #1: RSA Cryptography Specifications Version 2.2”是关于RSA算法实施的重要规范,详细定义了基于RSA...
PublicKey := RSA.ExportPublicPem; // 私钥保存为PEM格式 PrivateKey := RSA.ExportPrivatePem; end; ``` 接下来,我们讨论RSA加密解密。加密时,使用接收者的公钥将明文转化为密文;解密时,使用发送者的私钥...
在Java中,我们可以使用Java Cryptography Extension (JCE) 库来生成和操作RSA密钥对,包括公钥和私钥。 生成RSA公钥和私钥的基本步骤如下: 1. **创建KeyPairGenerator对象**:首先,我们需要创建一个...
在Java中,我们可以利用Java Cryptography Extension (JCE) 库来实现RSA的加密和解密操作。这个RAR压缩包中的内容可能包含了一些基础的RSA加密解密的Java源代码示例,对于初学者来说是很好的学习资源。 RSA的核心...
在Java中实现RSA加密需要理解其基本原理,并使用Java Cryptography Extension (JCE) 提供的相关类库。下面将详细介绍RSA加密算法的原理以及如何在Java中进行实现。 **RSA算法简介** RSA是由Ron Rivest、Adi Shamir...
6-Public-Key Cryptography_Eng.pdf 这份文档可能详细介绍了公钥密码学的概念和应用,以下是根据这个主题可能涵盖的一些知识点: 1. **基本概念**:公钥密码学的基础包括加密算法和密钥对的生成。加密过程中,发送...
在Java中,我们可以使用Java Cryptography Extension (JCE) API来实现RSA密钥对的生成。以下是对这个主题的详细阐述: ### RSA算法原理 RSA是由Ron Rivest、Adi Shamir和Leonard Adleman三位科学家于1977年提出的一...
在 JAVA 中,可以使用 Java Cryptography Architecture (JCA) 来实现 RSA 加密。JCA 提供了各种加密算法的实现,包括 RSA。下面是一个简单的 RSA 加密和解密示例: ```java import java.security.KeyPair; import ...
量子计算机能够以极快的速度执行特定的算法,例如著名的Shor算法能够在多项式时间内分解大整数和计算离散对数,这将直接威胁到RSA和ECC算法的安全性。书中会探讨当前量子计算的发展情况以及它们可能对公钥加密算法...