Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (seongtaejeong at gmail.com)
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)
(시리즈 글이 14개 있습니다.)
.NET Framework: 292. RSACryptoServiceProvider의 공개키와 개인키 구분
; https://www.sysnet.pe.kr/2/0/1218

.NET Framework: 327. RSAParameters와 System.Numerics.BigInteger 이야기
; https://www.sysnet.pe.kr/2/0/1295

.NET Framework: 329. C# - Rabin-Miller 소수 생성방법을 이용하여 RSACryptoServiceProvider의 개인키를 직접 채워보자
; https://www.sysnet.pe.kr/2/0/1300

.NET Framework: 356. (공개키를 담은) 자바의 key 파일을 닷넷의 RSACryptoServiceProvider에서 사용하는 방법
; https://www.sysnet.pe.kr/2/0/1401

.NET Framework: 383. RSAParameters의 ToXmlString과 ExportParameters의 결과 비교
; https://www.sysnet.pe.kr/2/0/1491

.NET Framework: 565. C# - Rabin-Miller 소수 생성 방법을 이용하여 RSACryptoServiceProvider의 개인키를 직접 채워보자 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/10925

.NET Framework: 566. openssl의 PKCS#1 PEM 개인키 파일을 .NET RSACryptoServiceProvider에서 사용하는 방법
; https://www.sysnet.pe.kr/2/0/10926

.NET Framework: 638. RSAParameters와 RSA
; https://www.sysnet.pe.kr/2/0/11140

.NET Framework: 1037. openssl의 PEM 개인키 파일을 .NET RSACryptoServiceProvider에서 사용하는 방법 (2)
; https://www.sysnet.pe.kr/2/0/12598

.NET Framework: 2093. C# - PKCS#8 PEM 파일을 이용한 RSA 개인키/공개키 설정 방법
; https://www.sysnet.pe.kr/2/0/13245

닷넷: 2297. C# - ssh-keygen으로 생성한 Public Key 파일 해석과 fingerprint 값(md5, sha256) 생성
; https://www.sysnet.pe.kr/2/0/13739

닷넷: 2297. C# - ssh-keygen으로 생성한 ecdsa 유형의 Public Key 파일 해석
; https://www.sysnet.pe.kr/2/0/13742

닷넷: 2300. C# - OpenSSH의 공개키 파일에 대한 "BEGIN OPENSSH PUBLIC KEY" / "END OPENSSH PUBLIC KEY" PEM 포맷
; https://www.sysnet.pe.kr/2/0/13747

닷넷: 2302. C# - ssh-keygen으로 생성한 Private Key와 Public Key 연동
; https://www.sysnet.pe.kr/2/0/13749




C# - ssh-keygen으로 생성한 Public Key 파일 해석과 fingerprint 값(md5, sha256) 생성

ssh-keygen 등으로 생성한 SSH public key의 경우, 다음과 같은 식의 포맷을 가지는데요,

// 여기서는 테스트를 쉽게 하기 위해 암호를 생략하도록 (-N 옵션의 빈 문자열) 지정했습니다. (현업에서는 암호 사용을 권장합니다.)

c:\temp> ssh-keygen -N "" -t rsa -b 4096 -f test_rsa
...[생략]...

c:\temp> type test_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvnNE7kvQyCLJIi3i1hZwVmLNheUb8E1oc3R94YLcnOKlisbuXx3hiSGjOPOx9Uedf/Pp73bx8Otu/9VudriZ910cPTzDDR6zJPfUYHyDiltwJ3zcKpkoG6z6ilIJVuX1Cm8S9q+pwkVOm7ij+FSiF8R/WxlblPMZzdTRyCYMCiOJ0KjZXU8as3iGadnQMZD+WUn6t/gPUKfIvCw1uAIPY5KDqp8RJeeMeJJw55RCkkjHzv1ghYvQDMCqpWXQ+OT5n1DQEpbH1994UYBJhpJC/W95+Tn2pqTPmcdobP7+nl3COVwxB77uk9Hxkfr9ldBxoZiEHchhm1qDUCp82QGFbImufQ3A2wYdQIyRTHD11gro17jj+5U7ae5szeRQzlh6RWaxUvPefFvs6nKhCXOE5yT5Ss5QoMBjivyUWdcMPW2X15dB0RAR03HA1GmyTnMj2zVJh/7p0hJR11U5EcOVQ969RfyPf7GvZZlhMSaYNdLiwg4O1f8FjS5wk+O7srimgnSe+K9Mz2qorCosYp4nZq/dduuy56UK2j609JbXXtfRRN0k16/JeDQvP7S1Pv3zQtwDvyBxGRlZ7UKhkAC1R0HRGjqWwqtVOTLtpKND64ENGXSYSddesF9SCBK2dwRjyhSLuv74dkpHzGbNAk0gTW1mnChJN6rHIrBtCA4rFRQ== testusr@TESTPC

이 포맷을 다음의 명령어를 이용해,

// 또는, openssl을 이용.
c:\temp> ssh-keygen -f test_rsa.pub -e -m pem > test_rsa.pub.pkcs1

c:\temp> type test_rsa.pub.pkcs1
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEAr5zRO5L0MgiySIt4tYWcFZizYXlG/BNaHN0feGC3JzipYrG7l8d4
YkhozjzsfVHnX/z6e928fDrbv/Vbna4mfddHD08ww0esyT31GB8g4pbcCd83CqZK
Bus+opSCVbl9QpvEvavqcJFTpu4o/hUohfEf1sZW5TzGc3U0cgmDAojidCo2V1PG
rN4hmnZ0DGQ/llJ+rf4D1CnyLwsNbgCD2OSg6qfESXnjHiScOeUQpJIx879YIWL0
AzAqqVl0Pjk+Z9Q0BKWx9ffeFGASYaSQv1vefk59qakz5nHaGz+/p5dwjlcMQe+7
pPR8ZH6/ZXQcaGYhB3IYZtag1AqfNkBhWyJrn0NwNsGHUCMkUxw9dYK6Ne44/uVO
2nubM3kUM5YekVmsVLz3nxb7OpyoQlzhOck+UrOUKDAY4r8lFnXDD1tl9eXQdEQE
dNxwNRpsk5zI9s1SYf+6dISUddVORHDlUPevUX8j3+xr2WZYTEmmDXS4sIODtX/B
Y0ucJPju7K4poJ0nvivTM9qqKwqLGKeJ2av3XbrsuelCto+tPSW117X0UTdJNevy
Xg0Lz+0tT7980LcA78gcRkZWe1CoZAAtUdB0Ro6lsKrVTky7aSjQ+uBDRl0mEnXX
rBfUggStncEY8oUi7r++HZKR8xmzQJNIE1tZpwoSTeqxyKwbQgOKxUUCAwEAAQ==
-----END RSA PUBLIC KEY-----

PKCS#1 PEM 포맷으로 변환할 수 있습니다. 이런 경우라면 닷넷 5부터 추가된 ImportFromPem / ImportFromEncryptedPem 메서드로,

C# - PEM 파일을 이용한 RSA 개인키/공개키 설정 방법
; https://www.sysnet.pe.kr/2/0/13245

공개키를 로드하는 것이 가능합니다.

string pemText = File.ReadAllText("test_rsa.pub.pkcs1");
using (RSA rsa = RSA.Create())
{
    rsa.ImportFromPem(pemText.ToCharArray()); // 현재 PUBLIC KEY, PRIVATE KEY, RSA PRIVATE KEY, RSA PUBLIC KEY 포맷을 지원합니다.
    Console.WriteLine(rsa.ToXmlString(false));
}

혹은, test_rsa.pub.pkcs1 파일 내부의 구분자를 제외한 내용을 ImportRSAPublicKey 메서드로 직접 로드할 수 있습니다.

string pemText = File.ReadAllText("test_rsa.pub.pkcs1");

var publicKeyBase64 = pemText
    .Replace("-----BEGIN RSA PUBLIC KEY-----", "")
    .Replace("-----END RSA PUBLIC KEY-----", "").Trim();

byte[] publicKeyBytes = Convert.FromBase64String(publicKeyBase64);

using (var rsa = new RSACryptoServiceProvider())
{
    rsa.ImportRSAPublicKey(publicKeyBytes, out _);
    Console.WriteLine(rsa.ToXmlString(false));
}




그렇다면 PEM 포맷으로 변경 없이 곧바로 읽어들일 수 있는 방법은 없을까요? 검색해 보면, 다음과 같은 글이 나옵니다.

Converting OpenSSH public keys
; https://blog.oddbit.com/post/2011-05-08-converting-openssh-public-keys/

위의 글에 따르면 SSH 공개키 파일 포맷은 다음과 같이 정의돼 있습니다.

  [The key type]  [A chunk of PEM-encoded data] [A comment]
예)ssh-rsa        AAAAB3...[생략]...cQ==         testusr@TESTPC

그다음, "[A chunk of PEM-encoded data]"의 포맷은 "key type"이 "ssh-rsa"인 경우 (length, data) 조합의 연속이라고 합니다. 3가지 값이 연속돼 있는데요, 이 형식은 다음과 같습니다.

[4바이트 길이(big endian)] [algorithm name, ("ssh-rsa" | "ssh-dsa")]
[4바이트 길이(big endian)] [RSA exponent (ASN.1)] 
[4바이트 길이(big endian)] [RSA modulus (ASN.1)]

따라서 C#으로는 이런 식으로 코드를 만들 수 있는데요,

private static (string algorithmName, byte[] exponent, byte[] modulus) DecodeSSHPublicKey(byte[] bytesEncoded)
{
    string algorithmName;
    byte[] exponent;
    byte[] modulus;

    using (var stream = new MemoryStream(bytesEncoded))
    using (var reader = new BinaryReader(stream))
    {
        int algorithmLength = reader.ReadInt32BE();
        algorithmName = Encoding.ASCII.GetString(reader.ReadBytes(algorithmLength));

        int exponentLength = reader.ReadInt32BE();
        exponent = reader.ReadBytes(exponentLength);

        int modulusLength = reader.ReadInt32BE();
        modulus = reader.ReadMPINT(modulusLength);
    }

    return (algorithmName, exponent, modulus);
}

public static class BinaryReaderExtension
{
    public static Int32 ReadInt32BE(this BinaryReader reader)
    {
        byte[] bytes = new byte[4];
        bytes[3] = (byte)reader.ReadByte();
        bytes[2] = (byte)reader.ReadByte();
        bytes[1] = (byte)reader.ReadByte();
        bytes[0] = (byte)reader.ReadByte();
        return BitConverter.ToInt32(bytes);
    }

    // RSA 공개키 등의 modulus 값에 0x00 선행 바이트가 있는 이유(ASN.1 인코딩)
    // https://www.sysnet.pe.kr/2/0/13740
    public static byte[] ReadMPINT(this BinaryReader reader, int length)
    {
        byte leadByte = reader.ReadByte();

        if (leadByte == 0)
        {
            return reader.ReadBytes(length);
        }

        reader.BaseStream.Seek(-1, SeekOrigin.Current);
        return reader.ReadBytes(length);
    }
}

그런데, 실제로 해보면 algorithmName, exponent 값은 제대로 읽어들이지만 modulus의 값이 틀립니다. 정상적인 경우와 비교해 보면, exponent를 읽어들인 후에 1바이트를 건너 뛰어야 한다는 차이가 있는데요,

int algorithmLength = reader.ReadInt32BE();
algorithmName = Encoding.ASCII.GetString(reader.ReadBytes(algorithmLength));

int exponentLength = reader.ReadInt32BE();
exponent = reader.ReadBytes(exponentLength);

reader.ReadByte();

int modulusLength = reader.ReadInt32BE();
modulus = reader.ReadBytes(modulusLength);

관련해서 검색해 보면 이런 글이 나옵니다.

Converting an RSA Public Key into a RFC 4716 Public Key with Bouncy Castle
; https://stackoverflow.com/questions/15457710/converting-an-rsa-public-key-into-a-rfc-4716-public-key-with-bouncy-castle

즉, exponent 다음에 1바이트 0x00이 추가된다고 합니다. 이게 4바이트 정렬 때문이라 그런 건지, (글에서처럼 puttygen을 포함해) ssh-keygen와 같은 도구에서만 그런 건지는 잘 모르겠습니다. (혹시 이와 관련해 아시는 분은 덧글 부탁드립니다. ^^)

참고로, "Converting OpenSSH public keys" 글에서 제시한 파이썬 예제 코드에도 딱히 1바이트를 건너 뛰어야 하는 코드가 없습니다.

import sys
import base64
import struct

# get the second field from the public key file.
keydata = base64.b64decode(
  open('key.pub').read().split(None)[1])

parts = []
while keydata:
    # read the length of the data
    dlen = struct.unpack('>I', keydata[:4])[0]

    # read in <length> bytes
    data, keydata = keydata[4:dlen+4], keydata[4+dlen:]

    parts.append(data)

아무튼,
저렇게 해서 로드하면 정상적으로 코드가 잘 동작합니다.

string text = File.ReadAllText("test_rsa.pub");

{
    string[] sshKeys = text.Split(' ');
    if (sshKeys.Length != 3)
    {
        throw new Exception("Invalid SSH Key");
    }

    string keyType = sshKeys[0];
    string comment = sshKeys[2];
    byte[] bytesEncoded = Convert.FromBase64String(sshKeys[1]);

    if (keyType != "ssh-rsa")
    {
        throw new NotSupportedException($"Unsupported key type: {keyType}");
    }

    (string algorithmName, byte[] exponent, byte[] modulus) = DecodeSSHPublicKey(bytesEncoded);
}

그리고 이렇게 구한 공개키 정보로부터 RSACryptoServiceProvider까지 초기화가 가능합니다.

RSAParameters rsaParam = new RSAParameters();

rsaParam.Exponent = new byte[exponent.Length];
rsaParam.Modulus = new byte[modulus.Length];

Array.Copy(exponent, rsaParam.Exponent, exponent.Length);
Array.Copy(modulus, rsaParam.Modulus, modulus.Length);

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParam);

Console.WriteLine(rsa.ToXmlString(false));

/* 출력 결과:
<RSAKeyValue><Modulus>r5zRO5L0MgiySIt4tYWcFZizYXlG/BNaHN0feGC3JzipYrG7l8d4YkhozjzsfVHnX/z6e928fDrbv/Vbna4mfddHD08ww0esyT31GB8g4pbcCd83CqZKBus+opSCVbl9QpvEvavqcJFTpu4o/hUohfEf1sZW5TzGc3U0cgmDAojidCo2V1PGrN4hmnZ0DGQ/llJ+rf4D1CnyLwsNbgCD2OSg6qfESXnjHiScOeUQpJIx879YIWL0AzAqqVl0Pjk+Z9Q0BKWx9ffeFGASYaSQv1vefk59qakz5nHaGz+/p5dwjlcMQe+7pPR8ZH6/ZXQcaGYhB3IYZtag1AqfNkBhWyJrn0NwNsGHUCMkUxw9dYK6Ne44/uVO2nubM3kUM5YekVmsVLz3nxb7OpyoQlzhOck+UrOUKDAY4r8lFnXDD1tl9eXQdEQEdNxwNRpsk5zI9s1SYf+6dISUddVORHDlUPevUX8j3+xr2WZYTEmmDXS4sIODtX/BY0ucJPju7K4poJ0nvivTM9qqKwqLGKeJ2av3XbrsuelCto+tPSW117X0UTdJNevyXg0Lz+0tT7980LcA78gcRkZWe1CoZAAtUdB0Ro6lsKrVTky7aSjQ+uBDRl0mEnXXrBfUggStncEY8oUi7r++HZKR8xmzQJNIE1tZpwoSTeqxyKwbQgOKxUU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
*/




해본 김에, fingerprint 값도 구해볼까요? ^^ 우선 ssh-keygen을 이용해 보면 공개키 파일의 fingerprint는 다음과 같은 명령어로 구할 수 있습니다.

// What is a SSH key fingerprint and how is it generated?
// ; https://superuser.com/questions/421997/what-is-a-ssh-key-fingerprint-and-how-is-it-generated

c:\temp> ssh-keygen -l -f "test_rsa.pub"
4096 SHA256:FfM9wFpzJqN5shtFtt+rk/0ggZbkGthsbsoZz52YiwQ testusr@TESTPC (RSA)

SHA256 해시를 했다는 것에서 대충 다음과 같은 코드를 작성할 수 있습니다.

string text = File.ReadAllText("test_rsa.pub");

string[] sshKeys = text.Split(' ');
string comment = sshKeys[2];
byte[] bytesEncoded = Convert.FromBase64String(sshKeys[1]);

// ...생략... (DecodeSSHPublicKey, RSACryptoServiceProvider 초기화)

string signature = Convert.ToBase64String(SHA256.Create().ComputeHash(bytesEncoded));
Console.WriteLine($"Fingerprint(sha256): {rsa.KeySize} SHA256:{signature.Replace("=", "")} {comment}");

/* 출력 결과:
Fingerprint(sha256): 4096 SHA256:FfM9wFpzJqN5shtFtt+rk/0ggZbkGthsbsoZz52YiwQ testusr@TESTPC
*/

출력 결과가 동일합니다. ^^ 또한, 예전처럼 md5 방식의 해시를 구하는 것도 가능한데요,

c:\temp> ssh-keygen -l -E md5 -f "test_rsa.pub"
4096 MD5:2e:fc:70:c6:6c:09:91:94:c2:4b:50:f5:75:47:ba:5c testusr@TESTPC (RSA)

C# 코드로는 이렇게 작성할 수 있습니다.

signature = BitConverter.ToString(MD5.Create().ComputeHash(bytesEncoded));
Console.WriteLine($"Fingerprint(md5): MD5:{rsa.KeySize} {signature.ToLower().Replace('-', ':')} {comment}");

/* 출력 결과:
Fingerprint(md5): 4096 MD5:2e:fc:70:c6:6c:09:91:94:c2:4b:50:f5:75:47:ba:5c testusr@TESTPC
*/




참고로, 자신의 코드가 제대로 동작하는지 확인하는 용도로 ^^ (비록 유료지만) 아래의 라이브러리가 쓸 만할 것입니다.

SshKey C# Reference Documentation
; https://www.chilkatsoft.com/refdoc/csSshKeyRef.html

Chilkat 라이브러리로 이번 글의 코드도 대충 다음과 같이 작성할 수 있습니다.

string text = File.ReadAllText("test_rsa.pub");
var sshObj = new Chilkat.SshKey();
sshObj.FromOpenSshPublicKey(text);

string xmlKey = sshObj.ToXml();
Console.WriteLine(xmlKey);
Console.WriteLine($"Fingerprint: {sshObj.GenFingerprint()}");

/* 출력 결과:
<RSAPublicKey><Modulus>r5zRO5L0MgiySIt4tYWcFZizYXlG/BNaHN0feGC3JzipYrG7l8d4YkhozjzsfVHnX/z6e928fDrbv/Vbna4mfddHD08ww0esyT31GB8g4pbcCd83CqZKBus+opSCVbl9QpvEvavqcJFTpu4o/hUohfEf1sZW5TzGc3U0cgmDAojidCo2V1PGrN4hmnZ0DGQ/llJ+rf4D1CnyLwsNbgCD2OSg6qfESXnjHiScOeUQpJIx879YIWL0AzAqqVl0Pjk+Z9Q0BKWx9ffeFGASYaSQv1vefk59qakz5nHaGz+/p5dwjlcMQe+7pPR8ZH6/ZXQcaGYhB3IYZtag1AqfNkBhWyJrn0NwNsGHUCMkUxw9dYK6Ne44/uVO2nubM3kUM5YekVmsVLz3nxb7OpyoQlzhOck+UrOUKDAY4r8lFnXDD1tl9eXQdEQEdNxwNRpsk5zI9s1SYf+6dISUddVORHDlUPevUX8j3+xr2WZYTEmmDXS4sIODtX/BY0ucJPju7K4poJ0nvivTM9qqKwqLGKeJ2av3XbrsuelCto+tPSW117X0UTdJNevyXg0Lz+0tT7980LcA78gcRkZWe1CoZAAtUdB0Ro6lsKrVTky7aSjQ+uBDRl0mEnXXrBfUggStncEY8oUi7r++HZKR8xmzQJNIE1tZpwoSTeqxyKwbQgOKxUU=</Modulus><Exponent>AQAB</Exponent></RSAPublicKey>
Fingerprint: ssh-rsa 4096 2e:fc:70:c6:6c:09:91:94:c2:4b:50:f5:75:47:ba:5c
*/

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




마지막으로 표준 관련 이야기를 해볼까요? ^^ "Converting OpenSSH public keys" 글에 따르면 ssh-keygen이 생성한 공개키 파일은 RFC 4253을 따른다고 합니다.

아래의 글에서 좀 더 자세하게 설명하는 글이 나오는데요,

OpenSSH public key file format?
; https://superuser.com/questions/1477472/openssh-public-key-file-format

일단, RFC 4251 문서("The Secure Shell (SSH) Protocol Architecture")상으로는 파일 포맷에 대한 규정이 없다고 합니다. 단지, 직렬화는 필요할 텐데, 재미있는 것은 SSH 프로토콜 협상에서 개인키가 오고 가는 것은 없으므로 그에 대한 직렬화도 스펙에는 없다고 합니다.

단지, 공개키라면 OpenSSH에서 파일에 저장하기 위해 RFC 4253 포맷을 많이 수용했다는 건데요, 파일 저장의 포맷이 규정된 것이 없으므로 클라이언트들이 개별 포맷을 사용하는 듯합니다. 그중 OpenSSH의 경우 내부적으로 OpenSSL을 사용하기 때문에 결국 OpenSSL의 공개키 파일 포맷이 곧 OpenSSH의 포맷이 됩니다.

별도로 "The SSH Public Key Format"으로 RFC 4716이 정의돼 있다고 하는데,

The Secure Shell (SSH) Public Key File Format
; https://datatracker.ietf.org/doc/html/rfc4716

그다지 일반적으로 차용되고 있지는 않다고 합니다. 이 문서 때문인지는 모르겠지만, 종종 Q&A에 보면 ssh-keygen으로 생성한 공개키에 대해 RFC 4716 포맷을 언급하는 글이 있기도 합니다. (혹시 표준 관련해서 잘 알고 계신 분은 덧글 부탁드립니다. ^^)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 9/30/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2024-10-18 08시23분
What's new in .NET 9: Cryptography improvements
; https://blog.elmah.io/whats-new-in-net-9-cryptography-improvements/

* KMAC (KECCAK Message Authentication Code)

* KMAC has minimum requirements for your system
  - Linux with OpenSSL 3.0 or later.
  - Windows system of Windows 11 Build 26016 or later.
정성태

1  2  3  4  5  6  7  8  [9]  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13718정성태8/27/20247411오류 유형: 921. Visual C++ - error C1083: Cannot open include file: 'float.h': No such file or directory [2]
13717정성태8/26/20247018VS.NET IDE: 192. Visual Studio 2022 - Windows XP / 2003용 C/C++ 프로젝트 빌드
13716정성태8/21/20246749C/C++: 167. Visual C++ - 윈도우 환경에서 _execv 동작 [1]
13715정성태8/19/20247348Linux: 78. 리눅스 C/C++ - 특정 버전의 glibc 빌드 (docker-glibc-builder)
13714정성태8/19/20246735닷넷: 2295. C# 12 - 기본 생성자(Primary constructors) (책 오타 수정) [3]
13713정성태8/16/20247444개발 환경 구성: 721. WSL 2에서의 Hyper-V Socket 연동
13712정성태8/14/20247214개발 환경 구성: 720. Synology NAS - docker 원격 제어를 위한 TCP 바인딩 추가
13711정성태8/13/20248055Linux: 77. C# / Linux - zombie process (defunct process) [1]파일 다운로드1
13710정성태8/8/20247974닷넷: 2294. C# 13 - (6) iterator 또는 비동기 메서드에서 ref와 unsafe 사용을 부분적으로 허용파일 다운로드1
13709정성태8/7/20247739닷넷: 2293. C# - safe/unsafe 문맥에 대한 C# 13의 (하위 호환을 깨는) 변화파일 다운로드1
13708정성태8/7/20247526개발 환경 구성: 719. ffmpeg / YoutubeExplode - mp4 동영상 파일로부터 Audio 파일 추출
13707정성태8/6/20247755닷넷: 2292. C# - 자식 프로세스의 출력이 4,096보다 많은 경우 Process.WaitForExit 호출 시 hang 현상파일 다운로드1
13706정성태8/5/20247881개발 환경 구성: 718. Hyper-V - 리눅스 VM에 새로운 디스크 추가
13705정성태8/4/20248145닷넷: 2291. C# 13 - (5) params 인자 타입으로 컬렉션 허용 [2]파일 다운로드1
13704정성태8/2/20248100닷넷: 2290. C# - 간이 dotnet-dump 프로그램 만들기파일 다운로드1
13703정성태8/1/20247429닷넷: 2289. "dotnet-dump ps" 명령어가 닷넷 프로세스를 찾는 방법
13702정성태7/31/20247827닷넷: 2288. Collection 식을 지원하는 사용자 정의 타입을 CollectionBuilder 특성으로 성능 보완파일 다운로드1
13701정성태7/30/20248098닷넷: 2287. C# 13 - (4) Indexer를 이용한 개체 초기화 구문에서 System.Index 연산자 허용파일 다운로드1
13700정성태7/29/20247698디버깅 기술: 200. DLL Export/Import의 Hint 의미
13699정성태7/27/20248225닷넷: 2286. C# 13 - (3) Monitor를 대체할 Lock 타입파일 다운로드1
13698정성태7/27/20248187닷넷: 2285. C# - async 메서드에서의 System.Threading.Lock 잠금 처리파일 다운로드1
13697정성태7/26/20247912닷넷: 2284. C# - async 메서드에서의 lock/Monitor.Enter/Exit 잠금 처리파일 다운로드1
13696정성태7/26/20247439오류 유형: 920. dotnet publish - error NETSDK1047: Assets file '...\obj\project.assets.json' doesn't have a target for '...'
13695정성태7/25/20247423닷넷: 2283. C# - Lock / Wait 상태에서도 STA COM 메서드 호출 처리파일 다운로드1
13694정성태7/25/20247889닷넷: 2282. C# - ASP.NET Core Web App의 Request 용량 상한값 (Kestrel, IIS)
13693정성태7/24/20247224개발 환경 구성: 717. Visual Studio - C# 프로젝트에서 레지스트리에 등록하지 않은 COM 개체 참조 및 사용 방법파일 다운로드1
1  2  3  4  5  6  7  8  [9]  10  11  12  13  14  15  ...