首页 > 解决方案 > 我如何拥有自己的公钥来加密数据?

问题描述

我有一个用户类,一个实体,它必须使用大小为 2048 的非对称密钥 (RSA) 以加密形式写入用户名和电子邮件。

信息将使用客户的公钥加密,他将使用他的私钥解密。

@Entity
public class Usuario implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String nome;

    private String email;

    @JsonBackReference
    @ManyToMany
    @JoinTable(name = "USUARIO_DIGITO", joinColumns = @JoinColumn(name = "usuario_id"), inverseJoinColumns = @JoinColumn(name = "digito_id"))
    private Set<DigitoUnico> resultadosDigitoUnico;
    
    ....
    getters and setters
    
}

在用户服务中,我调用为加密和解密创建的方法。

@Service
public class UsuarioService implements IUsuarioService {

    @Autowired
    private IUsuarioRepository usuarioRepository;   
    
....

    public Usuario adicionar(Usuario usuario) {
        
        usuario.setId(null);
        usuario.setResultadosDigitoUnico(null);
        
        try {
            return usuarioRepository.save(encriptarDadosUsuario(usuario));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    
        private Usuario encriptarDadosUsuario(Usuario usuario) throws Exception {
        usuario.setEmail(EncriptaDadosUsuario.encriptar(usuario.getEmail(), EncriptaDadosUsuario.gerarParDeChaves().getPublic()));
        usuario.setNome(EncriptaDadosUsuario.encriptar(usuario.getNome(), EncriptaDadosUsuario.gerarParDeChaves().getPublic()));
        return usuario;
    }
    
    private Usuario decriptarDadosUsuario(Usuario usuario) throws Exception{
        usuario.setEmail(EncriptaDadosUsuario.decriptar(usuario.getEmail(),EncriptaDadosUsuario.gerarParDeChaves().getPrivate()));
        usuario.setNome(EncriptaDadosUsuario.decriptar(usuario.getNome(),EncriptaDadosUsuario.gerarParDeChaves().getPrivate()));
        return usuario;
    }
}

但是,我必须创建一个端点来将此用户的公钥发送到客户端以进行加密。

我怎样才能拥有我的公钥,并将其用于此加密和解密?

在我的班级下面进行加密:

public class EncriptaDadosUsuario {

    public static KeyPair gerarParDeChaves() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("SHA256withRSA");
        generator.initialize(2048, new SecureRandom());
        KeyPair pair = generator.generateKeyPair();

        return pair;
    }
    
    
    public static String encriptar(String plainText, PublicKey publicKey) throws Exception {
        Cipher encryptCipher = Cipher.getInstance("SHA256withRSA");
        encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] cipherText = encryptCipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));

        return Base64.getEncoder().encodeToString(cipherText);
    }
    
    public static String decriptar(String cipherText, PrivateKey privateKey) throws Exception {
        byte[] bytes = Base64.getDecoder().decode(cipherText);

        Cipher decriptCipher = Cipher.getInstance("SHA256withRSA");
        decriptCipher.init(Cipher.DECRYPT_MODE, privateKey);

        return new String(decriptCipher.doFinal(bytes), StandardCharsets.UTF_8);
    }
    
}

标签: javaspring

解决方案


在使用“ SHA256withRSA ”实例化密钥对生成器和密码时,您尝试生成可用于签名但不能用于加密的 RSA 密钥。

您需要将 KeyPairGenerator 更改为“RSA”,将密码更改为“RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING”[或您的 Java 上的其他可用密码],以使您的代码运行。

您可以在下面找到包含更正的部分代码和一个小示例,该示例对电子邮件地址进行加密,然后将密文解密为解密后的文本。

请注意,此示例代码没有异常处理,仅用于教育目的。

输出:

How do I have my own public key to encrypt data
ciphertext: lVN6XLO7LxMASVifq2J1/T8Hv40AUeOml3+MjA6u+mKv1EcJHQO7gbZpMCrhO1fzo3s5tGRQl38iumMDqLBp+ApxQkPKeVVU99oOeuzYZb9fwyBH1/b4AEC1UDdFBWwH6rN/MuG17FyBrq/JR64upcM79gITdrIywvd32gYCd+XrGcGIxDoDGufQ1iqjjOihnRdYkYQDhUNEhi3clTz+ZDJ1EqMZmfc+v9Fsnsit2q9wbO3C33Hjbj/gY8AIMOpE7KYGupnpvR+WQk1DvmqiDoIDNfweRvwqF9m+7AUldAxxmjPN0C/WFmYPfZHUFSBK/0+8Ix5pDNw4l3C8thWKeg==
decryptedtext: myEmail@stackoverflow.com

代码:

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("How do I have my own public key to encrypt data");
        // string to encrypt
        String plaintext = "myEmail@stackoverflow.com";
        // keypair generation
        KeyPair keyPair = gerarParDeChaves();
        // encryption
        PublicKey publicKey = keyPair.getPublic();
        String ciphertext = encriptar(plaintext, publicKey);
        System.out.println("ciphertext: " + ciphertext);
        // decryption
        PrivateKey privateKey = keyPair.getPrivate();
        String decryptedtext = decriptar(ciphertext, privateKey);
        System.out.println("decryptedtext: " + decryptedtext);
    }
    public static KeyPair gerarParDeChaves() throws Exception {
        //KeyPairGenerator generator = KeyPairGenerator.getInstance("SHA256withRSA"); // used for signatures
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(2048, new SecureRandom());
        KeyPair pair = generator.generateKeyPair();
        return pair;
    }

    public static String encriptar(String plainText, PublicKey publicKey) throws Exception {
        //Cipher encryptCipher = Cipher.getInstance("SHA256withRSA"); // used for signatures
        Cipher encryptCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
        encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] cipherText = encryptCipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(cipherText);
    }

    public static String decriptar(String cipherText, PrivateKey privateKey) throws Exception {
        byte[] bytes = Base64.getDecoder().decode(cipherText);
        //Cipher decriptCipher = Cipher.getInstance("SHA256withRSA"); // used for signatures
        Cipher decriptCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
        decriptCipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(decriptCipher.doFinal(bytes), StandardCharsets.UTF_8);
    }
}

推荐阅读