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

... 46  47  48  [49]  50  51  52  53  54  55  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
3649kokon11/17/201520806예제 파일 실행이 안 되네요 [5]
3647Sang...11/15/201518607Part 3 목차? [5]
3646힘찬도약11/13/201524377c# mscorlib System.IO IOException [8]파일 다운로드2
3644힘찬도약11/11/201523145c# user.config파일 [2]
3645spow...11/13/201519596    답변글 [답변]: c# user.config파일 - Json.NET을 이용한 설정파일 처리 [1]파일 다운로드1
3643힘찬도약11/11/201521092C# 함수의 processing time과 재호출 [14]
3642.net11/10/201520426c# 으로 작성된 com+ 에 대한 문제입니다. [2]
3641힘참도약11/9/201520107c# log file 관련해서 질문드립니다. [5]
3638윤창선11/4/201522631사설IP가 부여된 무선라우터간 영상전송 관련 문의 [8]
3634Hyun...11/2/201519390c# 에서 webkit browser에서 webgl을 이용하는 사이트에 접속이 안됩니다. [1]
3633힘찬도약10/31/201519661mysql insert where not exists [6]
3632힘찬도약10/27/201519446C# Lock 관련해서 질문드립니다. [6]
3655iwc11/30/201517632    답변글 [답변]: C# Lock 관련해서 질문드립니다.
3631강준10/26/201521561iis 8.5 preload 기능에 대해 질문이 있습니다. [9]
3630김정훈10/25/201520039몬티홀 게임 관련 질문 [1]
3629pooq10/23/201520301리플렉션 관련해서 질문 입니다. [3]
3628최영민10/22/201518511스마트 클라이언트 로딩속도 문의입니다. [3]
3627양주호10/22/201518370C#으로 컨버팅 하려고 하는데요... [1]
3626조성진10/21/201519235책보고 첫번째 예제부터 문제가 생기네요 ^^; [4]파일 다운로드1
3623Bere...10/19/201520108질문이라기 보단... [2]
3625Bere...10/20/201518620    답변글 [답변]: 질문이라기 보단... [2]파일 다운로드1
3621힘찬도약10/18/201518908[C# 6.0]multi threading과 ui control [9]
3624힘찬도약10/19/201519080    답변글 [답변]: [C# 6.0]multi threading과 ui control [6]파일 다운로드1
3620popo10/13/201517514WPF의 datagrid, listview 컨트롤 관련 질문 입니다. [1]
3619링크의 ...10/12/201522321OCX 로드 관련 질문입니다. [5]파일 다운로드1
3616수요일밥...10/7/201523559몇 가지 오류 (2) [6]
... 46  47  48  [49]  50  51  52  53  54  55  56  57  58  59  60  ...