Microsoft MVP성태의 닷넷 이야기
vb.net 3.5버전 RSA복호화에 대해 여쭤봅니다. [링크 복사], [링크+제목 복사],
조회: 147
글쓴 사람
WMCH (oca123454 at gmail.com)
홈페이지
첨부 파일
 

using Microsoft.AspNetCore.Mvc;
using RsaApi.Models;
using RsaApi.Services;

namespace RsaApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class RsaController : ControllerBase
    {
        private readonly RsaService _rsaService;
        private readonly ILogger<RsaService> _logger;

        public RsaController(RsaService rsaService, ILogger<RsaService> logger)
        {
            this._rsaService = rsaService;
            this._logger = logger;
        }

        [HttpPost("generate")]
        public ActionResult<RsaGenerateKeyRequestDto> GenerateKey()
        {
            try {
                var result = _rsaService.generateKey();
                return Ok( new {
                        publicKey = result.getPublicKey(),
                        privateKey = result.getPrivateKey()
                     });
            } catch (Exception ex)
            {
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
            
        }

        [HttpPost("decryptMessage")]
        public ActionResult<EmrUserDto> getDecryptMessage([FromBody] DecryptMessageRequestDto request)
        {
            try {
                _logger.LogInformation(request.ciphertextBase64);
                return Ok(_rsaService.Decrypt(request.ciphertextBase64));
            } catch (Exception ex)
            {
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
            
        }
    }
}
using System.Security.Cryptography;
using System.Text.Json;
using RsaApi.Models;

namespace RsaApi.Services
{
    public class RsaService : IRsaService
    {
        private readonly ILogger<RsaService> _logger;

        // 생성자에서 ILogger를 주입받습니다.
        public RsaService(ILogger<RsaService> logger)
        {
            _logger = logger;
        }
        public RsaGenerateKeyRequestDto generateKey()
        {
            _logger.LogInformation("Key generation started.");
            // RSA 객체를 플랫폼에 맞게 생성
            using (var rsa = RSA.Create())
            {
                // 키 길이를 2048 비트로 설정
                rsa.KeySize = 2048;

                // 공개키와 개인키 추출
                var publicKey = rsa.ExportRSAPublicKey();
                var privateKey = rsa.ExportRSAPrivateKey();

                // Base64로 인코딩
                var publicKeyBase64 = Convert.ToBase64String(publicKey);
                var privateKeyBase64 = Convert.ToBase64String(privateKey);

                _logger.LogInformation(publicKeyBase64);
                _logger.LogInformation(privateKeyBase64);
                // DTO 리턴
                return new RsaGenerateKeyRequestDto(publicKeyBase64, privateKeyBase64);
            }
        }

        public string Encrypt(string plaintext, string publicKeyBase64)
        {
            using (var rsa = RSA.Create())
            {
                // 공개키 로드
                rsa.ImportRSAPublicKey(Convert.FromBase64String(publicKeyBase64), out _);

                // OAEP 패딩 방식 적용
                var encryptedBytes = rsa.Encrypt(System.Text.Encoding.UTF8.GetBytes(plaintext), RSAEncryptionPadding.OaepSHA1);

                return Convert.ToBase64String(encryptedBytes);
            }
        }

        public EmrUserDto Decrypt(string ciphertextBase64)
        {
            using (var rsa = RSA.Create())
            {
                _logger.LogInformation(ciphertextBase64);
                // 루트 경로에 있는 개인키 파일 경로 지정
                string privateKeyFilePath = Path.Combine(Directory.GetCurrentDirectory(), "private_key.pem");

                // 개인키를 파일에서 읽어서 Base64로 변환
                string privateKeyBase64 = ReadPrivateKeyFromFile(privateKeyFilePath);

                // Base64를 디코딩하여 RSA 개인키 로드
                rsa.ImportRSAPrivateKey(Convert.FromBase64String(privateKeyBase64), out _);

                // OAEP 패딩 방식 적용
                byte[] decryptedBytes = rsa.Decrypt(Convert.FromBase64String(ciphertextBase64), RSAEncryptionPadding.OaepSHA1);

                string result = System.Text.Encoding.UTF8.GetString(decryptedBytes);
                _logger.LogInformation(result);
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true // 대소문자 구분을 하지 않도록 설정
                };

                try
                {
                    // JSON 문자열을 EmrUserDto 객체로 역직렬화
                    return JsonSerializer.Deserialize<EmrUserDto>(result) ?? new EmrUserDto("", "", "", "", "");
                }
                catch (JsonException)
                {
                    // 역직렬화 실패 시 기본값을 반환
                    Console.WriteLine("Error during deserialization. Returning default EmrUserDto.");
                    return new EmrUserDto("", "", "", "", "");
                }
            }
        }

        private string ReadPrivateKeyFromFile(string filePath)
        {
            // 개인키 파일을 읽음
            string privateKey = File.ReadAllText(filePath);
            
            // PEM 형식에서 불필요한 부분 제거 (예: "-----BEGIN PRIVATE KEY-----"와 "-----END PRIVATE KEY-----" 부분)
            privateKey = privateKey.Replace("-----BEGIN RSA PRIVATE KEY-----", "")
                                .Replace("-----END RSA PRIVATE KEY-----", "")
                                .Replace("\n", "")
                                .Replace("\r", "");
            return privateKey;
        }
    }
}
using System.Text.Json.Serialization;

namespace RsaApi.Models
{
    public class RsaGenerateKeyRequestDto
    {
        private string publicKey;
        private string privateKey;

        public string getPublicKey(){
            return this.publicKey;
        }

        public string getPrivateKey(){
            return this.privateKey;
        }

        public RsaGenerateKeyRequestDto(string publicKey, string privateKey)
        {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }
    }

    public class RsaDecryptMessageDto
    {
        public string decryptMessage;

        public string getDecryptMessage(){
            return this.decryptMessage;
        }

        public RsaDecryptMessageDto(string decryptMessage)
        {
            this.decryptMessage = decryptMessage;
        }
    }

    public class DecryptMessageRequestDto
    {
        public string ciphertextBase64 { get; set; }
    }
    public class EmrUserDto
    {
        [JsonPropertyName("name")]
        public string Name { get; set; }

        [JsonPropertyName("birthday")]
        public string Birthday { get; set; }

        [JsonPropertyName("gender")]
        public string Gender { get; set; }

        [JsonPropertyName("phone")]
        public string Phone { get; set; }

        [JsonPropertyName("emrUserIdx")]
        public string EmrUserIdx { get; set; }

        public EmrUserDto(string name, string birthday, string gender, string phone, string emrUserIdx)
        {
            this.Name = name;
            this.Birthday = birthday;
            this.Gender = gender;
            this.Phone = phone;
            this.EmrUserIdx = emrUserIdx;
        }
    }
}

C#에서는 이런식으로 RSA암복호화를 진행하라고 예시를 줬는데
저는 VB.net 3.5에서 RSA복호화를 진행하려고 합니다.
private_key.pem은 제가 가지고 있고 서버에서 암호화된 문자열을 넘겨주면 RSA복호화를 통해 JSon형태의 데이터를 받아오도록 하길 원합니다.








[최초 등록일: ]
[최종 수정일: 7/17/2025]


비밀번호

댓글 작성자
 



2025-07-17 03시38분
VB.net 3.5라는 것은 아마도 .NET Framework 3.5 환경에서 VB.NET으로 코딩하시려는 의도같은데... 딱히 C#과 다른 점이 없습니다. 위의 예제에서 Decrypt 메서드에서 사용한 RSA 관련 타입들이 .NET Framework 3.5에서도 지원하기 때문에 그대로 VB.NET으로 마이그레이션하면 됩니다. 혹시... 뭔가 막히는 다른 부분이 있는 건가요?

그건 그렇고, 제시하신 예제 코드가 동작은 잘 하나요? 클라이언트 측에서 GenerateKey로 가져간 키는 RSA.Create로 새롭게 생성한 Key인 반면, getDecryptMessage 메서드에서는 클라이언트에서 "그 새롭게 가져간 키"가 아닌, 별도로 "private_key.pem" 파일에 저장한 Key를 사용해 복호화를 한다면 Key가 맞지 않아 문제가 됩니다.
정성태

... [91]  92  93  94  95  96  97 
NoWriterDateCnt.TitleFile(s)
189정성태5/10/200510818            답변글 [답변]: [답변]: [답변]: 네트워크 케이블의 연결상태 [2]
191최정희5/11/200510479                답변글 [답변]: [답변]: [답변]: [답변]: 네트워크 케이블의 연결상태 [1]
175안연준5/3/200510835IE 제어에 대한 궁금 증 ㅡ,.ㅡ;;
179정성태5/4/200511455    답변글 [답변]: IE 제어에 대한 궁금 증 ㅡ,.ㅡ;;
168안연준5/2/200510940[Database] Connection Error파일 다운로드1
169정성태5/2/200511109    답변글 [답변]: [Database] Connection Error
170안연준5/2/200510526        답변글 [답변]: [답변]: 계속 에러가 똑같애요
171정성태5/2/200511252            답변글 [답변]: [답변]: [답변]: 계속 에러가 똑같애요
172안연준5/2/200511115                답변글 [답변]: [답변]: [답변]: [답변]: 계속 에러가 똑같애요파일 다운로드1
173정성태5/2/200510870                    답변글 [답변]: [답변]: [답변]: [답변]: [답변]: 계속 에러가 똑같애요
174안연준5/3/200510867                        답변글 [답변]: [답변]: [답변]: [답변]: [답변]: [답변]: 계속 에러가 똑같애요
165장희석4/22/200511439[질문]ASP에서 ATL 서버 컴퍼넌트로 바이너리 데이타 전달하기
167정성태4/29/200511344    답변글 [답변]: [질문]ASP에서 ATL 서버 컴퍼넌트로 바이너리 데이타 전달하기
160카심4/21/200510851Internet Explorer 에서의 닷넷 Smart Client 개발
163정성태4/22/200510671    답변글 [답변]: Internet Explorer 에서의 닷넷 Smart Client 개발
159신대철4/21/200510560자동 로긴 프로그램
162정성태4/22/200510569    답변글 [답변]: 자동 로긴 프로그램
166신대철4/22/200510281        답변글 [답변]: [답변]: 자동 로긴 프로그램파일 다운로드1
157이용휘4/20/200510234w3ip를 통해서 윈도우 미디어 화을을 올려놓을 서버..
158정성태4/20/200510624    답변글 [답변]: w3ip를 통해서 윈도우 미디어 화을을 올려놓을 서버..
155최성우4/18/200512364[질문(--),(__)]BHO로 자동 로그인 기능 구현.. 패스워드를 읽어오지를 못합니다.
156정성태4/19/200511026    답변글 [답변]: [질문(--),(__)]BHO로 자동 로그인 기능 구현.. 패스워드를 읽어오지를 못합니다.
161최성우4/21/200512154        답변글 [답변]: [답변]: [질문(--),(__)]BHO로 자동 로그인 기능 구현.. 패스워드를 읽어오지를 못합니다.
164정성태4/22/200511032            답변글 [답변]: [답변]: [답변]: [질문(--),(__)]BHO로 자동 로그인 기능 구현.. 패스워드를 읽어오지를 못합니다.
176최성우5/3/200511258                답변글 [답변]: [답변]: [답변]: [답변]: [질문(--),(__)]BHO로 자동 로그인 기능 구현.. 패스워드를 읽어오지를 못합니다.
146안연준4/14/200512071컴포넌트 안에 컴포넌트 삽입? 헐 ! -_-;;
... [91]  92  93  94  95  96  97