Microsoft MVP성태의 닷넷 이야기
vb.net 3.5버전 RSA복호화에 대해 여쭤봅니다. [링크 복사], [링크+제목 복사],
조회: 205
글쓴 사람
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가 맞지 않아 문제가 됩니다.
정성태

... [31]  32  33  34  35  36  37  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
5139김이현3/28/201919426C#에서 CRON 같은 스케줄러를 사용하려면 어떻게 해야 하나요? [3]
5138김지원3/22/201916465유니티 쉐이더에서 오로지 포워드 애드 패스로만 만들 수 있을까요? [1]
5137세퉁3/22/201918129wpf 쓰레드에 대해 질문 있습니다. [4]
5136KGY3/13/201914848안녕하세요 닷넷코어 콘솔 프로그램 관련 질문입니다. [1]
5135러쎌3/13/201915403ASP.NET 공부 관련해서 문의를 드립니다. [1]
5134이정호3/12/201914312SampleProfiler 예제를 이용한 Class 객체의 접근 문의 [1]파일 다운로드1
5133ㅇㅇ3/12/201915462멀티코어사용 방법에 궁금한것이 있습니다. [3]
5132존기미3/3/201915736Physical Disk Access문의 [1]
5131강용규2/25/201915306c# 개발자입니다. 타이머 질문드립니다. [1]
5130노인코래방2/25/201919611C#에서 가장 좋은 성능을 보이는 파일 읽고 쓰는 방법이 무엇인가요? [2]
5129진우2/23/201918969닷넷 32비트 기반에서 메모리 부족으로 프로그램이 죽는경우 문의 [2]
5128게스트2/23/201916374안녕하세요. 초보개발자입니다. [3]파일 다운로드1
5127c#2/20/201915239책에 예제 문의드립니다. [2]
5125게스트2/19/201915208delegate를 활용한 event 를 적절히 불러오고 싶습니다. [2]
5124정근화2/12/201914938윈도우 서버2003 환경 오류 [2]
5123김주현2/8/201915040MS LUIS 에 대한 소개 하실 계획이 있으신가요? [1]
5122jaka...2/1/201917692Clickonce 배포 후 Command 실행 [2]파일 다운로드1
5121엔벌이1/31/201917106C# DataGridView의 MDB파일 함수? ArrayList? [1]파일 다운로드1
5120임우진1/30/201917965웹에서 응용프로그램 바로 실행하기 관련 브라우저에서 파라미터가 넘어오지 않습니다.ㅜㅜ [2]
5119guest1/29/201919700교재에 오탈자 있어 알려드리려 합니다 [1]
5118WPF꿈...1/26/201917997GetHashCode 메서드에 대해서 [1]
5117하주형1/25/201917870List<int>에 대한 이해가 잘안됩니다. [5]
5116게스트1/24/201915859asp.net 관련 gridview webform 질문 드립니다. [1]파일 다운로드1
5115Soul...1/24/201916415투명 패널 질문드립니다. [2]
5114박현일1/20/201917057WPF DataContext 관련 초보 질문을 드려봅니다.^^ [5]
5113하주형1/20/201916325안녕하세요 시작하세요 C# 인코딩관련 질문드립니다. [1]
... [31]  32  33  34  35  36  37  38  39  40  41  42  43  44  45  ...