Как мне получить свой собственный открытый ключ для шифрования данных?

#java #spring

#java #spring

Вопрос:

У меня есть класс пользователя, сущность, и он должен записать имя пользователя и адрес электронной почты в зашифрованном виде с помощью асимметричного ключа (RSA) размером 2048.

Информация будет зашифрована с помощью открытого ключа клиента, и он будет расшифровывать, используя свой закрытый ключ.

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

Ответ №1:

Вы пытаетесь сгенерировать ключи RSA, которые можно использовать для подписи, но не для шифрования, при создании экземпляра keypairgenerator и шифровании с помощью «SHA256withRSA».

Вам нужно изменить 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);
    }
}
  

Комментарии:

1. Спасибо за ответ. Мне нужно, чтобы мой пользователь получал этот открытый ключ, и при отправке данных для регистрации, например, он также отправляет мне этот ключ, и я выполняю шифрование. Итак, я отправил keypair.getpublickey() бы контроллер via или ресурс? Прежде чем он отправит мне данные для шифрования?

2. Я не совсем уверен, каков ваш рабочий процесс. Допустим, у нас есть ОТПРАВИТЕЛЬ и ПОЛУЧАТЕЛЬ. ПОЛУЧАТЕЛЬ отправляет свой открытый ключ ОТПРАВИТЕЛЮ. ОТПРАВИТЕЛЬ шифрует свои секретные данные с помощью открытого ключа, полученного от ПОЛУЧАТЕЛЯ. ОТПРАВИТЕЛЬ отправляет свой зашифрованный текст ПОЛУЧАТЕЛЮ. Только ПОЛУЧАТЕЛЬ может расшифровать секретные данные с помощью своего закрытого ключа. Вам решать, как вы отправляете открытый ключ отправителю (существует несколько способов форматирования для кодирования ключа и последующего восстановления открытого ключа).

3. Мой пользователь должен получить открытый ключ. Чтобы при отправке его данных я использовал этот открытый ключ, полученный им ранее, для шифрования его данных. Итак, мой вопрос в том, если я отправлю ему это getPublicKey() , сработает ли это шифрование, которое будет позже? мой открытый ключ не обязательно должен быть исключительно для этого пользователя.