Microsoft MVP성태의 닷넷 이야기
vb.net 3.5버전 RSA복호화에 대해 여쭤봅니다. [링크 복사], [링크+제목 복사],
조회: 203
글쓴 사람
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)
4783후배12/13/201619201MemoryStream에 관한 질문 입니다. [5]
4782김형민12/6/201617889[ C# 6.0 ] 126p 오타인가요? [6]
4781질문자11/29/201617996ms워드 저장 오류 [1]
4780최진11/28/201622587안녕 하세요 빌드 관련해서 질문드립니다 꾸벅 [4]
4779손니11/28/201618911안녕하세요 질문하다 드려도 될까요 [3]
4778김상호11/25/201618008재귀호출->비재귀호출 [2]파일 다운로드1
4777권오영11/12/201620944아래 질문 상세 소스전체입니다.. [3]
4776권오영11/11/201618775제가 이클립스를 공부중인데..이상한것을 찾았습니다.. [2]
4775이성환11/11/201622530안녕하세요. SnapsToDevicePixels 질문입니다. [5]파일 다운로드1
4774popo11/10/201619091.net SSL통신 관련 질문 드립니다. [1]
4773김상호11/4/201620873재귀함수 반복문 변환 [1]파일 다운로드1
4772자연인10/27/201622202hwpctrl을 사용하는 사이트에서 나와 브라우저를 종료하면 오류메세지가 나옵니다. [1]파일 다운로드1
4771문종훈10/18/201622069.net 소스 질문이 있습니다 [2]
4770누구게~...10/15/201619403세도나 [1]
4769spow...10/13/201617707올리시는 게시물에 '좋아요'를 선택할 수 있도록 해주세요 [3]
4768브라운10/11/201619464질문 하나만 드려도 될까요 [4]
4767암호군10/4/201624944c# aes 128 암복호화 관련 문의드립니다. [3]
4766김신철9/29/201619524Visual Studio 2015에서 .net 3.5로 c# 6.0 사용시 문제점에 대해서 궁금합니다. [1]
4765spow...9/23/201618541참조를 통해 속성의 값을 변경하고 싶을 때 우아한 코딩 방법이 있을까요? [2]
4764지현명9/22/201620442Visual Studio 2008 c#에서 추가된 솔류션의 디버깅이 안걸립니다. [2]파일 다운로드1
4763송기태9/20/201618666안녕하세요! 질문이 있어 문의드립니다! [1]파일 다운로드1
4762김신철9/20/201619867Visual Studio 2015 마이그레이션 후 빌드 및 에러 문제.. 도와주세요~ [2]
4761JH9/19/201620309WPF로 Viewbox 사용 시 폰트 크기 일정화 여부 [1]
4760초보9/18/201621627유닉스서버(HP)에서 C# 서버 프로그램 실행 가능 한지요? [1]
4759dev009/16/201623107Queue out of memory [3]
4758임기성9/12/201621616MS오피스 워드 64비트에서 32비트 COM개체 사용방법 문의 [2]
... 31  32  33  34  35  36  37  38  39  40  41  42  43  [44]  45  ...