在《在Linux下如何使用openssl生成RSA公钥和私钥对》一文中,讲述了在Linux环境下如何生成RSA公钥和私钥,但在Java中,我们又是如何去很好的用它们呢?下面我来看下两个案例,特别是RSA私钥的生成是有输入密码的(在生产环境上一般都应该是这样用的),即在产生密钥对时有输入密码,如输出了12345678。
一.加签验签
import java.io.File; import java.io.FileReader; import java.io.IOException; import java.security.KeyPair; import java.security.PrivateKey; import java.security.Security; import java.security.Signature; import java.security.interfaces.RSAPrivateKey; import java.util.Arrays; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMReader; import org.bouncycastle.openssl.PasswordFinder; import org.bouncycastle.util.encoders.Hex; public class SignatureExample { public static void main(String [] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); String message = "hello world"; File privateKey = new File("C:/Users/alexbi.WEBANK/Desktop/test/key"); KeyPair keyPair = readKeyPair(privateKey, "12345678".toCharArray()); Signature signature = Signature.getInstance("SHA256WithRSAEncryption"); signature.initSign(keyPair.getPrivate()); signature.update(message.getBytes()); byte [] signatureBytes = signature.sign(); System.out.println(new String(Hex.encode(signatureBytes))); Signature verifier = Signature.getInstance("SHA256WithRSAEncryption"); verifier.initVerify(keyPair.getPublic()); verifier.update(message.getBytes()); if (verifier.verify(signatureBytes)) { System.out.println("Signature is valid"); } else { System.out.println("Signature is invalid"); } } private static KeyPair readKeyPair(File privateKey, char [] keyPassword) throws IOException { FileReader fileReader = new FileReader(privateKey); PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword)); try { return (KeyPair) r.readObject(); } catch (IOException ex) { throw new IOException("The private key could not be decrypted", ex); } finally { r.close(); fileReader.close(); } } private static class DefaultPasswordFinder implements PasswordFinder { private final char [] password; private DefaultPasswordFinder(char [] password) { this.password = password; } @Override public char[] getPassword() { return Arrays.copyOf(password, password.length); } } }
二.通过JSch上传文件到SFTP,并从SFTP服务器上下载
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStream; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.Security; import java.util.Arrays; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMReader; import org.bouncycastle.openssl.PasswordFinder; import com.google.common.io.Closeables; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; public class SftpUtil { public static final String PASSPHRASE = "12345678"; /** * 上传文件 */ public static void upload(String user, String ip, int port, String privateKeyPath, String remoteFileName, String remoteFilePath, String localFileName) throws Exception { ChannelSftp sftp = null; FileInputStream input = null; Session sshSession = null; try { Security.addProvider(new BouncyCastleProvider()); JSch jsch = new JSch(); sshSession = jsch.getSession(user, ip, port); // 判断鉴权方式 jsch.addIdentity(privateKeyPath, PASSPHRASE); sshSession.setConfig("StrictHostKeyChecking", "no"); sshSession.connect(); Channel channel = sshSession.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp) channel; if (sftp != null && sftp.isConnected()) { File file = new File(localFileName); input = new FileInputStream(file); if(StringUtils.isNotEmpty(remoteFilePath)) { sftp.cd(remoteFilePath); } sftp.put(input, remoteFileName); sftp.quit(); } } finally { if (input != null) { try { Closeables.close(input, false); } finally { input = null; } } if (sftp != null) { try { sftp.disconnect(); } finally { sftp = null; } } if (sshSession != null) { try { sshSession.disconnect(); } finally { sshSession = null; } } } } /** * 下载文件 */ public static void download(String user, String ip, int port, String privateKeyPath, String remoteFileName, String remoteFilePath, String localFileName) throws Exception { ChannelSftp sftp = null; OutputStream output = null; Session sshSession = null; try { Security.addProvider(new BouncyCastleProvider()); JSch jsch = new JSch(); sshSession = jsch.getSession(user, ip, port); // 判断鉴权方式 jsch.addIdentity(privateKeyPath, PASSPHRASE); sshSession.setConfig("StrictHostKeyChecking", "no"); sshSession.connect(); Channel channel = sshSession.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp) channel; if (sftp != null && sftp.isConnected()) { if(StringUtils.isNotEmpty(remoteFilePath)) { sftp.cd(remoteFilePath); } output = new FileOutputStream(localFileName); sftp.get(remoteFileName, output); sftp.quit(); } } finally { if (output != null) { try { Closeables.close(output, false); } finally { output = null; } } if (sftp != null) { try { sftp.disconnect(); } finally { sftp = null; } } if (sshSession != null) { try { sshSession.disconnect(); } finally { sshSession = null; } } } } public static void main(String[] args) throws Exception { //upload("sftpuser", "10.107.97.20", 57001, "C:/Users/bijian/Desktop/test/key", "a.txt", "", "C:/Users/bijian/Desktop/bijian.txt"); download("sftpuser", "10.107.97.20", 57001, "C:/Users/bijian/Desktop/test/key", "alexbi.txt", "", "C:/Users/bijian/Desktop/bijian02.txt"); } }
参考文章:https://stackoverflow.com/questions/1580012/using-a-pem-encoded-encrypted-private-key-to-sign-a-message-natively