모드 설명 특징
ECB (Electronic Codebook) 동일한 평문 블록이 항상 같은 암호문 블록으로 변환됨 간단하고 빠름
CBC (Cipher Block Chaining) 이전 암호문 블록을 XOR하여 암호화 패턴 숨김 가능, 보안 강화
CFB (Cipher Feedback) 암호문 일부를 피드백하여 스트림처럼 동작 메시지 크기 제한 없음
OFB (Output Feedback) 내부 상태를 이용한 스트림 모드 에러 전파 없음, 동기화 가능
CTR (Counter Mode) 증가하는 카운터 값을 암호화하여 XOR 병렬 처리 가능, 성능 우수
GCM (Galois/Counter Mode) CTR 기반으로 인증 기능 추가 무결성 검증(AEAD 지원), 빠름
XTS (XEX-based Tweaked CodeBook mode with CipherText Stealing) 디스크 암호화에 특화됨 특정 크기 데이터 보호에 적합

사용하면 안 되는 AES 모드

  1. ECB (Electronic Codebook)
    • 동일한 입력이 동일한 출력으로 변환되므로 패턴이 보존됨보안 취약
    • 예제: 이미지 암호화 시 패턴이 남음 (펭귄 이미지 문제)
  2. OFB (Output Feedback) 및 CFB (Cipher Feedback)
    • IV를 재사용하면 키 스트림이 반복되어 보안이 깨질 위험이 있음
    • 동기화 문제가 발생할 경우 전체 데이터가 손상될 가능성 존재

추천하는 AES 모드

  1. GCM (Galois/Counter Mode)
    • AEAD (Authenticated Encryption with Associated Data) 지원
    • 무결성 검증 기능 포함 → 데이터 변조 감지 가능
    • 빠른 속도와 병렬 처리 가능
    • TLS 1.2/1.3에서 가장 많이 사용됨
  2. CTR (Counter Mode)
    • 빠르고 병렬화 가능
    • IV(Nonce) 관리만 잘하면 안전
  3. XTS (XEX-based Tweaked CodeBook mode with CipherText Stealing)
    • 디스크 암호화용으로 가장 적합
    • BitLocker, APFS 등에서 사용

새롭게 출시된 JAVA24에서 PQC를 지원한다.

CRYSTALS-Dilithium(ML-DSA)를 지원한다고 해서 테스트를 해보았다. FALCON(FN-DSA)는 아직 미지원인듯 하다.

파라미터 공개키 개인키 서명
ML-DSA-44 1312 2560 2420
ML-DSA-65 1952 4032 3309
ML-DSA-87 2592 4896 4627
package org.example

import java.security.KeyPair
import java.security.KeyPairGenerator
import java.security.Signature

fun main() {
    // ML-DSA 키 쌍 생성
    val keyGen = KeyPairGenerator.getInstance("ML-DSA-44")
    val keyPair: KeyPair = keyGen.generateKeyPair()

    // 개인키 & 공개키 원본 데이터 및 크기 출력
    val privateKeyBytes = keyPair.private.encoded
    val publicKeyBytes = keyPair.public.encoded

    println("Private Key (Raw Bytes): ${privateKeyBytes.joinToString(" ") { "%02X".format(it) }}")
    println("Private Key Size: ${privateKeyBytes.size} bytes")

    println("Public Key (Raw Bytes): ${publicKeyBytes.joinToString(" ") { "%02X".format(it) }}")
    println("Public Key Size: ${publicKeyBytes.size} bytes")

    // 메시지 서명
    val signature = Signature.getInstance("ML-DSA")
    signature.initSign(keyPair.private)
    val message = "Quantum-Secure Message".toByteArray()
    signature.update(message)
    val signedMessage: ByteArray = signature.sign()

    // 서명 데이터 원본 및 크기 출력
    println("Signature (Raw Bytes): ${signedMessage.joinToString(" ") { "%02X".format(it) }}")
    println("Signature Size: ${signedMessage.size} bytes")

    // 서명 검증
    signature.initVerify(keyPair.public)
    signature.update(message)
    val isValid: Boolean = signature.verify(signedMessage)

    println("Signature Valid: $isValid")
}
Private Key (Raw Bytes): 30 82 0A 18 02 01 00 30 0B 06 09 60 86 48 01 65 03 04 03 11 04 82 0A 04 04 82 0A 00 43 53 FD 67 AE 49 30 DE 92 DE E1 CE AB AB 10 AA 88 4A CC 48 8D 70 CE 32 42 C8 71 5B 70 8A 25 11 39 14 FE 92 F3 9B F7 68 06 58 5D CE 57 DC 16 D6 AE 12 41 52 30 7D F0 72 AB FE DE 85 61 4B 0A 19 29 F8 A5 E1 67 38 78 04 EF 7E 6E 16 31 BE 98 09 77 58 5B 37 C2 AB 52 28 97 42 FF 52 D5 D8 DE CD 07 95 37 2A 03 14 2B 4D D6 CB EB 6C 2A CA 72 0C 80 F7 27 86 0B 5C CB 96 D5 16 63 E2 BE F4 61 4B 11 A5 30 61 42 26 1C 37 41 99 84 08 D9 06 72 62 C4 8C 03 41 85 5B 30 65 88 32 69 DC 90 25 D9 22 40 02 93 11 81 82 21 1C 22 8D 4B 12 2C 11 48 82 89 14 24 23 38 24 48 C8 40 1C C7 28 DA 02 44 CA 92 80 0A 17 30 92 28 71 5A 26 65 8A 20 50 01 12 09 04 41 45 CC 94 08 01 93 60 14 C7 2C 83 96 01 10 89 81 82 94 8C 02 28 62 52 42 02 1B 08 24 0B 13 29 D9 12 51 1B 10 11 53 00 31 0A B0 24 1A A7 8D 98 B2 4C 1B 94 68 20 84 2D A0 10 82 01 96 09 9A 28 30 0A 19 2E 10 02 49 14 88 69 1C 40 28 44 34 69 21 87 65 63 06 30 11 89 90 53 B2 49 0C 80 45 1A 16 65 00 A4 50 1A 41 8D 1A C5 50 0B 38 8E 0A 42 10 5A B4 2C 5A 42 6E D9 B2 8D C1 00 66 DB 14 8C E0 38 26 C1 A0 69 93 A8 65 20 98 2D 80 C0 08 54 30 46 54 C6 91 42 B6 6D 0A 83 60 9C 96 21 E3 02 50 08 24 8C C2 16 21 14 C7 45 80 34 69 51 20 88 00 43 8E 1A C6 60 0C B5 24 E4 04 10 C4 30 82 0B 07 28 18 48 69 CB 90 69 02 38 26 60 48 12 92 38 52 0B 25 88 4A 22 21 C8 26 91 49 16 4E 01 28 09 23 A8 6D 10 93 08 49 22 0C 04 10 30 91 18 86 13 48 09 24 27 48 92 02 52 A2 C0 10 92 16 84 08 34 90 20 B2 50 E0 16 61 0B 01 80 40 32 00 11 21 81 0A 28 69 4B 80 11 9C 34 2C A2 90 90 01 17 09 18 B4 31 58 84 90 22 18 92 41 A6 88 1C 08 8A 4A 86 69 43 44 70 14 19 08 9C 34 4C 24 28 21 9C 86 45 53 24 49 5A 30 2C 20 B6 41 A0 20 06 13 83 50 E3 12 44 90 10 02 C2 A2 09 23 14 06 9C 36 6A DB 30 09 0C 09 02 23 B5 41 12 98 69 5B A2 01 9A 26 64 4B 28 68 C9 00 08 0A 17 89 C9 36 06 09 00 00 D8 20 10 10 18 41 E2 38 04 54 10 70 DA 38 32 9C 04 90 63 48 0D 08 32 72 53 B0 8D 22 49 90 4C 42 25 82 14 25 1C 46 61 0A 41 22 1A 35 2C 02 24 61 11 12 8D 11 29 10 08 94 30 22 27 46 CB 30 49 04 C3 6C 18 C2 91 0A 42 61 C4 C4 09 E4 A8 88 80 26 22 9C 36 0C D4 24 60 98 90 6C 20 80 61 CB 32 29 E1 86 51 1B 38 82 E2 82 29 44 42 2C 04 C3 31 40 04 2D 42 30 09 23 26 85 23 B8 20 22 99 28 D3 A8 68 21 A5 49 E3 B0 71 04 87 04 14 04 49 13 45 89 58 36 48 8A C0 8C 21 47 21 21 04 40 44 B0 6D CC C2 84 C9 04 80 64 82 31 D0 02 86 94 08 4A 09 05 80 1A C3 8C C1 12 31 CC 96 05 24 81 20 53 A6 09 9B 88 01 D9 86 89 98 36 91 8A 26 64 A3 02 4E 22 08 51 40 B0 50 C4 C2 71 52 20 45 80 90 6D 18 B6 81 CC 88 20 C4 28 71 12 16 0E A2 22 25 09 04 50 14 31 51 D3 46 01 22 82 71 48 44 70 02 A0 30 24 85 48 11 08 04 4C 28 20 24 05 0A 5B 04 28 DA 14 00 21 45 42 89 94 31 12 A4 01 A1 06 6C CB 96 31 9A 06 50 A2 30 06 1A 34 09 5C 06 42 C2 28 48 01 41 CE 83 4B 0A A8 56 C8 4A 97 9C F3 CB 35 49 09 73 EB 1C E8 87 62 CB D5 5D D0 62 D5 40 7C 23 69 97 29 1D BF D4 09 9A C5 95 C6 E3 A6 CE FC 04 68 C6 1E 5B 66 C1 DD 0E 70 23 F1 31 77 28 5F 91 1E AE 23 9A 73 96 B0 72 2C D8 89 9C 31 00 40 54 3F A5 86 56 08 50 1F 00 6F EA C6 CB 54 7A C8 5E 75 3D A5 5B 35 EC 0E DE CB 3C 09 E7 E5 F1 31 D4 9E 33 C3 E7 86 3A 26 63 53 4A DB FB 4B 15 A7 C9 82 6D B9 36 A4 64 D7 BC C1 36 53 09 1A D9 95 80 72 92 6A DB E8 EC 12 40 E3 68 BA 41 30 FC 05 FF BA 67 C5 2D B4 32 A1 3F 39 FD 46 E2 2B 7A 8D EB 01 63 08 27 7D 92 16 57 1A 74 54 DC F3 5C 07 C2 CB 38 CF B8 44 FC 7E 07 98 ED 65 12 58 DD C1 EB 1D 67 F1 38 4D 34 7D 47 F9 A9 16 5D F2 A7 05 23 C9 15 08 86 AC F1 CD B5 BB 1C C3 30 07 EC 88 14 C3 01 24 23 C3 9D 8C D9 DF E2 EB 08 06 B0 A5 24 9F FD 4C 0B AE 0A AE A9 70 DE 64 03 85 E6 29 EE 45 17 69 17 D4 EF 6B EA E9 4B EB C9 A9 BE C7 02 1C 8A 1F 79 40 49 32 D7 83 29 DA 49 73 8D 5B 7F 36 89 41 73 63 3C E8 B3 AD 96 31 B0 A1 C6 05 06 C6 D0 86 FC 44 35 82 CC 50 24 B8 B3 34 AA D3 82 E5 99 A9 5C DC 02 AD 00 92 F8 EA 4E 9E F3 02 CA 6C 9C E3 72 36 47 0C 5A 64 FD 39 33 79 22 38 7B EC 74 55 CB E8 A1 22 D1 5A 4E 32 28 08 FF 86 58 7E 6A 83 2B 10 6F D5 E0 EE 02 6D 22 4A BC 80 BD 95 AA AF 2D C1 DC 51 76 F4 8D 6B 5F 83 25 D8 B7 47 B9 5B D2 4E E2 43 9B 5E 0E 3D 51 C6 EA EC EE 86 6D CC 91 3C 81 0B C3 40 DA 1E 8E D7 88 AC AA BD EA 1D 79 72 DA 45 CB AE 1D 2B 69 B2 B2 3D 66 B4 41 17 DE 91 E5 ED 2F 67 82 58 BF 1D F4 68 D5 01 DA A2 A9 71 4D 7F ED DD 0E A6 B4 02 3C D9 2A FE 7D 9F DB 0D 09 94 B9 9F 00 56 84 3A 03 9B 72 F7 04 1D CD 7A 8A E7 C2 BD A4 4D 4A 9E DC 23 7D C8 78 43 59 0B C4 A3 F9 72 1C 75 46 97 86 FD AC 7E 16 86 FD 4B 8F AD 64 7B E9 A4 30 29 75 18 C8 6D BF DA 1E AC 28 3D 69 8C F7 16 A0 24 7F 00 52 D7 BF 9C DC 5D 92 20 AE C4 B8 4B 27 99 F8 32 B2 42 F9 5E A3 7F 2F 2C 47 3A DD 53 04 F1 83 C2 B9 E9 48 5B EA 49 41 BB 82 D0 19 51 50 CB FC 85 52 C3 97 12 9D B6 82 49 95 8B AB 6C 84 64 E6 ED 65 96 74 74 49 4F 4C 5F B8 9A A8 F0 2A 25 BF 1E 05 59 E0 4D F1 EA 9D 6D 2C A6 88 41 E1 95 90 18 66 D3 1E 5A 4E 39 71 B6 3E E3 1F 2B B6 0E 56 A0 4B 58 49 CB 19 28 83 7E 64 9A 7E DD 19 56 CD 2F 4B 6E A4 90 39 3B 4E 56 16 D2 FA AD 6D F0 9A 82 53 FF 57 82 A9 1A AB 6E AE 3B 21 9B 30 5C 20 39 EA 99 6C E4 F4 9C 9E 35 4C 68 6B 6F 8A 41 28 5C B1 3B 4C E6 F2 C6 11 21 A8 4E 2F C8 70 73 3B 11 35 05 4F E5 9D DB 8A 63 20 60 33 17 58 D6 59 57 ED 5B 8F DB 50 60 05 D9 D1 3C 6F BE 30 84 08 1C 42 65 0E 17 8B 5B CD 71 FD 82 04 E2 F5 02 76 64 E7 58 4C AD B4 74 8F 80 DD DA D2 1F 30 68 69 B2 C8 A8 FD 5C 70 69 CB 42 2B 94 11 23 0E 73 B9 0D F8 FA 37 0A 20 D9 DA 9A C8 CF D4 E3 9D AB 8F CC 0D 52 B4 8E 3D FC 73 C0 5A 04 6C 0E 68 64 02 92 45 DB 8E 2B D0 35 2B 08 73 19 DC 58 60 62 AE 32 A4 87 DB 85 D2 44 0C 74 93 3D A8 61 CF E6 80 FB 51 39 C5 29 61 59 C9 43 61 47 65 17 49 86 D3 E0 A4 AB 94 F4 6C 8A 40 8C 94 E2 34 0F 96 55 7D B2 76 81 15 7F 35 26 11 F9 22 40 77 B8 7A 51 A8 EC BC 32 13 E2 2E 10 0F A2 AC 53 26 49 4C 27 F7 50 04 18 8C 57 CC 57 C6 F4 5D E1 72 38 8E 90 26 F3 8E 96 39 8C 5F C6 80 FA E5 B0 C3 5F 4B AD 44 92 18 1E 80 15 B2 30 7E 75 27 06 B8 07 E3 DF 08 71 55 50 F8 C4 0A D5 97 B5 9C 8B 50 A9 07 B7 43 BF 8C 29 C8 06 06 B7 BC B7 B2 18 EB 8E 70 03 7F 20 93 21 AF BA FA 15 73 F0 BC F9 76 3D 13 CD 30 D2 99 E6 E0 CA E6 DA 2A 42 E9 DB 56 BB B6 05 10 90 85 E2 E5 3F 22 B9 FD 3A 97 E7 9E 5F D9 FB 6C FF C8 C6 5F 4D 30 EA 63 83 AF 1A 8B 82 5F 6D 80 49 D2 9A F5 25 B7 39 53 4A 57 21 33 0E 20 6F 30 F5 6B BE 39 88 60 8B 2B BC BF 30 3D DA ED B4 1F 95 47 FF 26 7D 9F 5C 19 D6 38 29 3E 89 77 E8 EF 70 11 A9 80 44 24 D9 B3 97 97 ED 16 BE CF 41 85 A6 91 6B 69 44 34 D4 AB 1E 21 75 32 E7 5E DA 55 43 A1 A7 88 F0 58 FD 65 25 1D BA 46 9D 6D 95 42 90 63 B8 C4 6E 26 AD 7C 55 8C BB C8 69 15 E1 3E BB CF 12 2F 57 B7 F5 E0 82 31 9C B7 45 0C 6E 5A 50 B6 CD F6 ED FD 99 AF 0D 21 81 32 80 02 D7 6F 13 56 F0 FA 07 EE 3D A3 12 05 4E 87 FC 0D 19 44 BF 30 49 23 83 D4 73 F5 4B D4 0A 2B 29 EB 45 D2 6F 86 C8 DC A0 1A 75 90 35 7A 0D A7 C3 D1 E3 5E B0 AB 74 0F 6F C0 38 26 95 A5 70 8A 41 82 DC 88 83 BA 22 6A 84 B5 43 EE 2E C5 89 38 13 8C 73 5F F6 DF F2 3F A5 4D A9 58 2D D5 12 22 C5 19 5D 8E D4 43 86 51 06 4D 7F FC A6 CD 32 E5 88 AC E9 2D 46 10 D5 30 5D 03 86 E5 66 24 01 71 00 AE 75 CE B0 62 8C EA 3F EB C3 EE 77 44 68 E5 91 F1 E5 88 6C A7 22 1A 1E 69 F1 3F A1 C2 7E B3 75 58 B5 E4 ED 20 C7 F9 96 26 CB 05 94 60 9E 35 1F 0C F5 D6 3F 17 3A 81 3D 33 E4 BF 17 91 35 D6 DC D5 11 02 92 1F C7 6B 0E 12 8D 11 0F E9 D1 A7 77 D7 E4 6F 00 43 CB F5 D8 51 3C F0 AC 52 29 32 5B CA 92 D0 F7 4A E3 C6 EC 51 79 CD CC 61 E5 78 25 62 43 5E 8A E8 8B 56 D8 1C AD 0F 01 52 50 AD B3 38 44 E7 61 42 B7 02 69 DB 38 C5 22 19 0B 6F 34 7D BD 8A 69 AF 96 B0 B7 D5 21 8D 79 44 4C 3D 95 5A D5 95 0D 10 AA 37 57 C2 90 26 32 73 7A BC 80 8C AD 50 5C 23 81 6D 93 FB D1 A0 12 D0 0B BE 55 9B 6B F2 BB 0F FA FC A5 A6 D8 B0 98 85 C9 FB 05 76 DF F7 5E 10 B2 DA 88 CA 9D C4 D0 33 A1 09 37 76 C8 DA 14 65 FF 38 77 11 A0 C2 FE 7B B7 10 55 EE B5 38 96 E5 EE AC 45 B6 6F 88 79 0E 9B 40 5B 81 85 19 68 52 02 F2 5E A7 06 83 03 6D 9C 38 E1 C1 F4 EC 51 EC
Private Key Size: 2588 bytes
Public Key (Raw Bytes): 30 82 05 32 30 0B 06 09 60 86 48 01 65 03 04 03 11 03 82 05 21 00 43 53 FD 67 AE 49 30 DE 92 DE E1 CE AB AB 10 AA 88 4A CC 48 8D 70 CE 32 42 C8 71 5B 70 8A 25 11 1F D3 6C 80 7A DD 05 44 D5 70 7C 95 C9 52 E0 9A A9 E2 FB C7 C8 97 75 56 EB 23 8E 9E C0 AB A7 24 FC 3C C3 62 0A C7 CF 7F 79 3B 73 4F D7 81 0A 74 9D C0 B5 54 09 84 D0 01 00 4E B5 41 89 D9 08 7E BE EA E3 6A 5B 0F C9 38 A4 17 FD 37 34 6A 79 1F 4A 57 4F 28 78 FF BA 6C C7 3F 69 AB 75 DA 6A 8A BD 61 CC 4E F8 B4 28 36 1F 5A 4C 92 82 A9 49 10 51 6C 0E A7 90 C6 3D 8D 52 5C 1F A4 BD 05 0E BF 2E C0 0A D7 16 6A 7C CA E6 28 AB 2A 9A 7E E7 75 05 25 EF 23 4F 2E 93 AD 4F B4 F6 7B D1 15 75 53 27 27 83 01 E0 0C E7 D8 74 CE 9D C8 B7 42 25 7D 2F D6 C8 D7 3A 18 8B E5 74 79 20 13 8B E2 8B D0 04 54 67 18 3A E9 0F 90 6A C6 2D 39 D9 C4 AD 35 EF FA BA A4 CA BF B5 D1 83 A7 28 B4 E9 F8 E3 2C 68 1B 9C CD 5C E2 38 9A EA E9 C1 27 5A F6 43 BF 79 C3 2D 70 DB 64 09 D4 0B 6F 4C 65 A5 0A A9 59 62 44 1E B2 06 02 17 69 7E 41 95 66 A8 2C D4 1C E0 69 34 DC CF 8A 04 35 69 1F F6 5F FA 59 B8 54 AA BD 7A EC 5F B8 F5 A3 5F 93 A4 9D F6 31 80 C2 10 BE 75 02 4C 3D 94 D2 0F C9 04 2A 3C E4 C9 82 C9 2B B3 3E 12 C4 2A 09 82 E3 B4 0E 28 95 BC F4 AD DB B9 22 7C 0F 77 B5 B5 0E F2 9F CF 87 42 5E BD 41 D2 9F DD DA 03 9F 48 DA B5 C8 D3 41 88 A2 D5 F2 9F FD 2E 72 4F F6 79 75 3F A7 3F 22 D5 AA 22 74 00 52 25 6F 3C 72 02 54 3C C3 F5 13 31 DC 7D 9B B4 56 DB C8 9D C3 23 90 93 F7 6D 3E 32 94 05 6B 73 06 0F EF 9A 83 5E 46 F9 76 48 D6 8A F1 A9 B3 36 42 D0 97 17 E0 29 BF B8 1A BF 6E 68 DD 45 39 8E 6B 54 76 35 50 AF 83 7F 7A 97 63 2B 41 96 ED FF EF 35 43 6F 63 BE DA DC D1 C9 17 9F C3 E7 3D 6C FF 38 56 23 EA 94 21 42 BF EC A5 75 83 2C 0B 59 46 7A B8 D4 93 1D 7D 42 DD 53 B3 88 8D 14 AE 50 4C 14 2D 0E 30 EF 09 0E 8C 32 FE 02 29 39 A2 0E 7E 9A FB D4 23 4F F7 E2 31 1C 65 4D 24 1D 6C 5C A7 2A 8F 07 BA B7 3B 9A 8D 68 F2 D1 EE 28 FA 8E E1 AC 69 64 E1 DB 52 29 BB 30 E6 F2 11 04 CF D3 C4 A9 3E D1 A2 B4 50 DD 2B 6C 9C 4E BC 62 0A 97 08 AC 10 CA 77 3C FB 38 95 B8 DF 8F BD 7D 71 E7 98 21 CD 58 02 62 FF B7 B1 47 9D 79 81 A3 14 9B EA 76 A6 2B E4 A2 6F F9 DA F3 7C 77 85 B9 AE 72 5E 3E DC 1B 55 FC 76 03 78 71 0F 48 C4 23 21 D1 AB C2 C0 44 19 54 42 D6 63 25 5F 19 8A 8E C0 5D DE 02 1D A9 25 34 75 AC D0 FD AD 85 5F B8 44 48 5C 5F F7 5E 03 6D D9 CD 35 10 54 01 06 64 2A B0 07 8D E7 7D B5 A3 BC 1A A2 37 8D C6 FA F6 36 7D 5B 46 3D AB 25 7A 43 0F 4E C9 6F 74 02 C9 DD 54 B8 1F 0A 5C 65 3A D5 2C 0A 84 F7 CA 9D 8A 4D 6F 21 13 C8 9D 8E 99 32 8C DD 8C 77 91 07 5E C5 58 A6 01 76 75 FB 91 4D 58 F7 18 0D A3 B7 2D ED 9C F5 38 8C 2C EE B0 96 04 D0 01 7B 96 4E 6D 06 4B 47 D1 E1 04 8D E5 37 21 65 4E 22 E6 BB 1C B7 10 65 0A 9E 5A 5A EA 41 C3 18 27 7C 19 F6 0F 24 E1 4C CD B2 2A B4 E2 C9 45 39 28 DC 30 B3 95 7A EA C3 ED 93 C4 0A F8 2F F5 CB 9F D5 7B E8 05 97 78 87 70 CF 0F 18 44 4C CA C8 42 BF 67 35 9D 73 A9 B1 55 4B 11 8E A7 84 E1 98 C7 10 0B C7 C7 E0 83 DB 65 38 43 9B 74 68 95 55 54 0F C2 B4 63 1A E8 A5 4A A0 D8 F9 80 19 8F 37 DC 84 37 08 93 E7 E8 67 50 BC 87 B2 52 24 31 0F 53 73 F8 4B EB 5C AB 35 08 71 BC 83 45 96 8E BA E9 45 1B 8C 7B 74 C5 6D EE DE 4E D8 CE 59 01 A6 41 FB A9 92 A5 9D 18 32 FA 84 C7 32 0A 60 5D 1B 24 03 B9 68 84 E0 47 0D 2B E0 83 9D 1B 9E 71 F8 AB EE 0D C8 B8 60 A5 7B F5 5D 75 62 CF 0E 2F 43 23 2D A3 75 15 3B D9 85 E4 97 2F CF E2 49 30 98 5F 10 28 91 81 6C 8D F5 36 E6 53 13 BA 85 4A 0E 50 54 91 F2 60 77 E0 4D 33 1D AB 46 BE DA 57 6E 3C 0D 50 C4 A2 A9 76 91 0E 7B 33 6A 46 BF 8F 79 65 53 D6 80 89 7E 43 5E D7 71 27 8A FA 91 D3 2A E9 CC 81 7A B5 84 CB BF A5 A4 5E D5 26 69 E1 24 F2 05 F0 83 FC C7 35 70 35 D9 3A BE 77 7A 8E 76 B0 1E B9 98 72 75 2F B0 01 DE 9E 54 2C 25 2D 9D B6 BF 07 04 FE 63 10 7F 93 6E 48 0B AD B7 DA 1A 00 FC 1C 70 56 C2 14 39 2C 61 CD F2 A7 0A C9 8D F3 FD 15 FE 18 38 BD B8 AA B9 09 EA 8F 51 11 B1 55 69 F3 1C 5F 89 D5 69 BA 4F 81 7B 55 20 CE 1F 87 E0 8D 0D 01 DA E0 C0 3D 89 F6 2B FE E6 49 E9 99 57 DD 32 AA 47 03 8D FD 14 63 C6 A7 99 B8 06 38 DE 82 DC A1 4D 72 4E 4E 0F 3F 34 50 74 76 CE FA 7B 40 02 4C 7C 12 59 7E 24 62 48 08 18 55 4D FF 40 4B 54
Public Key Size: 1334 bytes
Signature (Raw Bytes): 27 CB 90 27 A3 68 7A 85 E3 88 8E 22 32 A9 46 5E 6F 0E B4 1B 3D 5B 36 98 C4 FA F2 02 52 79 B2 4C 7F 27 94 5B 0E FF 2D CD 23 CF 5D 14 4B 27 61 0A DA 7A 19 38 3E B2 4E 81 7D 42 18 1F BB CB 51 97 7A 08 BF A2 7D C1 78 92 45 3A FA 0E B2 AF 22 3C 9E D2 8D 72 6F 2F 6A 28 BB 2F 54 03 DA 2C 56 CE E2 A2 49 98 A4 9B F5 B7 EA 61 03 82 D9 01 3F 34 78 1E 46 E2 D9 A1 E0 3F C2 8D FF BC 9B 74 3B 62 47 79 8B 37 A6 74 A0 F8 18 79 09 98 52 D2 1F 78 85 50 7E CE 9F D7 28 31 BC 5C 5E CC FE ED C9 56 65 D3 66 DB 9F 63 5D FD 8B 3E F5 19 70 42 6E 6B 91 EF D0 44 DC 33 95 F1 7D C7 B0 E0 AD 75 C1 F7 4D D7 A2 DC 4D 0B 4F 7C 6D 1B D1 89 A6 E5 31 E4 ED AA 43 C6 7D 7F F6 E0 47 9F FE 76 27 18 C5 AE DA 5C 21 6E FA AC 0A 2B 3A 67 AF A8 58 CF 8C 0E E6 59 21 51 0A 62 FA C5 87 AE 8D 86 D9 7D C1 B4 C1 2D D7 13 4C A4 BB E0 36 03 02 20 2D 18 7D F3 B3 A3 15 3D 26 E7 14 64 4B B4 4F 7A 47 EE 2F 32 26 1C E6 BB 0F 13 38 50 12 93 52 F0 9E 76 3F 6D E1 FD 35 7F 20 FF D9 E5 F3 C8 BF 84 AC 96 7A F8 9C 3B 1B B9 77 D1 87 DE D1 EE E2 86 64 3C 17 E4 8E C0 C8 E2 EF 10 ED A0 E5 09 EC 02 9F C0 34 0F 20 BA F4 BC 13 62 CD 11 6E 93 FE 01 D9 CC 90 59 C9 F5 0E AD D6 ED B7 97 EE 3C A7 17 F8 07 40 C2 A6 E0 C3 D8 1F C5 34 4D C5 C9 66 8E 6E 28 62 D2 13 51 2E F7 70 CA 26 BD A1 C9 A6 A1 3B 7D E8 E2 9D BB 7B 63 F4 07 99 C5 EE 07 B7 10 1B 44 30 B1 75 24 B5 F1 98 7D 1F 5E 15 9C 46 84 23 EC A3 3B D4 54 DF 69 FC CD 72 50 DE 6E D0 55 E5 49 BF 7F F3 B9 13 E2 F2 3A 22 6F EC 84 56 03 86 CF 13 91 E9 0A 31 46 03 1E EE 25 0A 1F 44 93 BC BA FA 44 09 7F A3 01 6B 54 EC EC C4 32 79 0D EE AA 1D 2A 20 0F CF 27 08 9C CC 39 90 08 77 19 C2 76 74 69 AA 00 CD C5 99 18 D7 4D B0 6E FD 99 17 DD 16 93 50 D7 2C 4B 78 10 DF 87 59 A2 05 04 81 8C CF AE 7A 45 84 87 84 0A 62 F2 A9 95 59 68 AD AF 18 33 32 60 D3 3B B4 31 FF 72 BA C4 9F DB 82 E0 33 6D E3 40 10 5D 99 EF 52 AA 50 A9 F3 9F 0F A5 36 7D 3A 8A 6A F5 DD 42 DC 1D B6 D0 1C 93 9E 41 96 99 7F DE 3B 4F 00 AF EB 0D CA BA 15 BF 0D E1 D8 20 A7 DD 89 C6 AD 1F 72 72 7F 43 00 D3 1A AD CF 3E 0F E6 03 67 E0 9F BF E9 17 E2 2B 00 EF EF 24 48 E2 03 FE A1 18 0C 4F 6B A6 E6 F8 76 FA B5 11 4C B4 05 37 4B 1A 39 58 2C 64 5B 00 5A FC F4 60 F0 29 44 3E 19 AD 5F 80 36 E3 FD F7 84 39 5B B4 0F 9B 04 DC B6 01 EE E2 82 E7 F3 D5 B6 5C FD A0 01 AC ED 76 4F 07 8F 6C F0 CC CD 12 68 10 8D C8 AC FB 49 71 66 8E 8A 16 A0 6A 71 05 7E F1 5E 7C 76 A3 D2 49 D2 21 6A FB 04 AA F1 70 43 78 40 35 B0 7A 06 48 D4 9A 46 52 A8 FE 3A 4F B7 1C 5E F0 09 8F E8 BD D0 7D 74 71 70 D1 24 85 44 C2 FD A3 43 D2 12 4E D1 1F 97 88 BE 8D AC 7A 1A 9F C4 48 C3 33 D4 F4 F2 C5 FF 93 02 83 AE 83 51 3D CA 7E 5D 85 1B 18 ED B4 92 49 BA A6 55 23 BF E3 CE E9 AB C5 97 69 F5 F6 45 11 C8 60 5F 8F DB 4B 54 9F 92 B3 14 8A 53 08 80 8D 91 F8 E4 DF 6A 78 FA C5 95 F4 79 6A D0 78 6F 1F AE 22 21 26 1D 02 B3 59 A5 A4 01 A0 01 D6 24 2D 37 78 31 7E 25 59 01 01 D6 99 A0 73 FA CB CD 7B FD C4 A6 6F AD 79 0E AF DC 95 F0 9A 35 15 3F 12 A1 F1 F2 C8 87 44 F6 6E D7 84 21 27 A1 BE C7 A2 0F AB 34 30 87 D1 77 3A E7 F8 F7 57 B5 3C 02 73 FF 67 E4 D1 C4 0D E7 91 22 57 3E F6 BA 93 7C E3 C3 E7 B4 E7 A9 79 F8 93 76 BC CA A3 1E D8 CB E2 EE E1 BB F8 2A AB B8 2A 55 09 05 14 B7 9E 6E 75 78 36 70 D2 03 4A 1D 68 C6 67 6D 48 B0 3B D6 04 59 CA 37 FE 55 17 A9 41 59 69 97 1C 9A 67 C4 DD 64 25 B9 A6 B3 83 F6 2B C5 75 F7 59 9C 17 09 C3 F8 96 E2 A5 67 5A FF 0B 5C 33 C9 07 5C A9 41 FA 8A 8D 6A 4F BC DE 8E B1 20 17 39 CE DD 5E 1D 13 67 C8 67 2A 5C 31 43 6F BD 25 77 DD DD A6 35 A8 BC 14 AB AC 52 86 EB 1C 5F 77 3E C9 F2 99 48 41 30 86 36 80 CC 0C F6 0F 84 03 4A 45 98 1E 8D 48 97 E4 FE 44 BC DD A2 E0 87 C3 D8 8F EE D0 F6 0D A0 AB 83 A3 94 C6 C5 DA ED 2B B8 02 32 76 BA 5A AA 43 E2 BD 5E 7B 67 87 04 36 83 7E 93 49 65 F3 1F E4 B8 9D EA 51 52 F3 00 41 3C 99 01 DF E8 D4 58 17 80 A6 BD FE C4 57 FD 9E B1 93 59 0A 71 39 EF 4F 03 B8 60 80 DE 3A 21 11 D7 7B 7B CE 89 FE 73 5A FF 24 36 5A 18 2E 31 4C D5 8B 0F 85 2C 42 95 57 2A 74 72 69 68 D6 EB F6 6D 2F 40 86 FB 1A 24 EF C5 29 09 0A 92 BA B0 3D DB DC 1F A4 5D 14 D1 75 28 79 0A 10 39 FA 97 BD 5E 5C D8 C1 70 9F 49 24 22 74 9D E8 A5 D5 45 5A 36 05 84 9E F8 0F 6E 62 EC 1D AE F6 04 8A CD 0F 90 C8 0F 77 4E 46 F7 CB 8A A7 DE 45 4E 9C D3 6A 39 EC 48 14 14 06 95 AD 18 E1 E3 03 33 35 0B 01 4E D3 00 55 49 F0 D4 70 14 B1 71 27 12 E7 E9 57 ED BB 1D 4F B1 D3 1B D8 FB 62 47 B6 8A 2F EC A9 B0 2F 3A A4 26 F6 BB 52 F6 88 8B 00 A7 F9 33 DA 1B F5 D6 3E CD 36 1D AA E9 A8 DC 1D EF 76 2E 6B EB E5 00 DD C8 F1 24 15 DE F6 52 28 A3 C0 83 EF D2 17 82 43 D3 9E AA DA 21 B0 89 66 C5 D6 ED 1F 08 29 AC BD A7 25 F7 59 78 35 5D 0A 38 C1 AA 1A AB 07 25 84 75 9F 9F C9 01 64 05 24 08 9A EC 88 68 8C 1F 23 C3 D1 B6 C5 DA F7 AD AF 0B 0F B3 40 6B EA 65 F0 D7 17 DD EA AA E7 6A BD 7F F8 58 69 97 2A FF 77 A3 D0 B2 2D 03 87 24 59 27 3A 81 A8 41 47 BD A4 AD 2B B6 79 5D B0 A1 2F C3 6B BC 89 58 54 30 B6 4B F8 4E EF DA FF CB 34 69 FD 13 6F 08 DD B5 74 19 25 FB E9 4D 87 66 73 9E 82 10 F4 24 64 FC EB 90 E1 20 D1 50 28 75 10 2C 33 D2 6C 5F 2B FB 60 6B 83 49 07 23 8A A5 AE 82 49 12 5A 8B A1 40 A8 71 11 AB 3F EA D6 13 63 B9 57 1E 23 09 C0 2F CF 25 22 E4 96 AB 7A 91 C2 32 4E BD 91 AB 2C 92 C9 69 FC D8 D0 74 18 11 D0 47 98 DB 83 68 C5 9D AD 1E 28 36 45 95 16 99 8B 1F 9E 05 AC DC 63 41 67 A8 EF 48 25 D7 C6 F0 F7 7B F9 42 3B 91 A6 51 B9 29 D4 E7 C4 8D BE 71 ED 47 44 13 DF 8C 6A F8 EE B1 21 3C A0 49 21 9C E6 4A AA D9 BA EA 9F CF 7C 74 F3 AA AD 88 0F ED 65 7A 0C 1A 5B 66 27 5C EF AC 19 BB 04 CC 52 C4 0D C4 84 99 5E 94 D2 DB AB 12 39 87 6A AD CE E7 D8 80 CC D2 9B C8 0D FF CB 35 E8 70 53 EC D7 EF 8D 42 75 25 37 FA D9 66 DD FB D2 25 FD 62 2E 74 99 4F 08 FB D8 FB 44 A1 11 5C D6 5D 21 F2 0A FB EE 44 DA 82 7B 15 51 A6 17 A2 6A DC 9D 30 90 E4 98 40 C8 F9 91 1C B0 09 BE 40 81 FF 77 2A AE 5C 88 50 F4 15 CE 2F 38 FA 11 39 C5 CC 2A 9C F2 99 01 96 3B 14 61 97 9D 72 0C BA 90 5F 51 64 48 B1 D7 09 5D AA EF 55 52 60 C3 24 B7 7F 30 A8 7F 6F A9 8D 17 9D 24 84 2A 5D 64 72 FB 49 38 1F CC 00 5F 06 0A 23 05 45 20 56 81 8B B4 F4 0D F9 49 56 29 C8 AE 6A CE 3C 31 4E 55 09 A6 71 05 0E 7B C0 F5 42 CA 0B 33 BC 3A D0 14 C9 40 DA 54 EA BB 54 A5 EE E6 BF 67 A7 C6 51 4F 96 89 A1 E6 F6 99 58 39 8A 9E A4 34 91 FA 6C A4 06 F9 03 02 74 00 11 E8 B0 E2 9B 58 76 E9 6F 43 E8 0D DD 19 6B 92 9F 9E 28 95 4B 93 CB 87 B1 08 90 B4 62 83 F0 BE DD 13 66 3F CB 7F 7B 5C 66 7A 40 BE F3 6D B4 68 E6 93 AD EE 2C 34 AB 58 C5 8F 83 45 4A 69 D9 43 49 C5 D3 8E 1C 6F 37 84 37 16 88 79 B5 B2 20 BB FF 5F 23 C1 CA F8 DA 5D CA 1A 9A 79 5C B7 91 BC 49 73 E0 6E BF C5 AD 6C 8C 73 0B 97 69 D4 77 86 9B 69 00 F2 AE 2B 5E 28 B0 05 B9 FB 14 AA 0B B3 32 40 0D B0 15 C2 D9 A8 D3 7D 12 60 DB D0 EA F4 BF 21 AC 7A EE 91 B8 D2 47 4A 55 66 4F 17 0A 0C 04 09 5C C9 73 6A D2 EC 7C BB B5 A8 37 1D 66 19 1D F8 DF 09 69 C2 43 1A 60 BB 44 73 6A EB 1F 29 C9 35 A9 62 D4 E2 50 BA 60 05 9D 3C DA 75 57 B4 D2 52 96 CC 30 63 1D 9C 13 B7 3E D8 DB 06 AA 33 88 A8 E6 53 6A 52 89 7C 3F 60 BE 73 DA BB D3 FF B9 56 2C F4 B9 3E 84 89 24 E8 73 B0 37 F5 C5 C3 D9 79 66 DF CB D0 8D 8D DE 07 28 36 D9 A6 81 34 68 6D 8B 8B 83 91 C2 8E BB 18 06 B4 3D C0 6B 94 94 01 41 80 E8 F7 38 4C 0D 59 5E 6A 0A 09 58 B2 13 0B 38 AA 9D 4F AD 30 23 F6 85 50 0A 3C 9E DF 78 4F 95 8B 67 04 11 24 3B 77 78 A8 CC D2 E5 F2 F3 54 5A 5E 76 79 7B 92 BB DD FF 01 0B 13 2D 2E 42 45 54 5D 5E 78 B4 B7 C5 D5 D7 03 3B 3E 44 49 51 5D B7 BB EA EC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 16 26 31
Signature Size: 2420 bytes
Signature Valid: true

ASN1 DER를 파싱하면 스펙의 사이즈와 일치하는 것을 확인할 수있다.

 

'Applied Cryptography' 카테고리의 다른 글

AES 운영 모드 비교  (0) 2025.03.28
ECIES-X963-SHA256-AESGCM  (0) 2025.03.17
[EC] 디지털 서명 3종  (0) 2025.03.16
[양자내성암호] Kyber 찍먹해보기  (0) 2025.02.20
전자서명(pkcs#7)과 전자봉투  (0) 2019.12.22

ECIES-X963-SHA256-AESGCM을 살펴보자.

ECIES  ECDH(키 교환) 후 대칭키 암복호화를 수행하는 것을 의미
X963-SHA256  공유키 유도 방식
AES-GCM  AES 대칭키 암호화. GCM은 MAC 역할
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.hashes import SHA256
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
import os

# AES-GCM 암호화 함수
def aes_gcm_encrypt(key, plaintext):
    iv = os.urandom(12)  # GCM IV (12바이트)
    cipher = Cipher(algorithms.AES(key), modes.GCM(iv))
    encryptor = cipher.encryptor()
    ciphertext = encryptor.update(plaintext) + encryptor.finalize()
    return iv, ciphertext, encryptor.tag  # (IV, 암호문, 인증 태그)

# AES-GCM 복호화 함수
def aes_gcm_decrypt(key, iv, ciphertext, tag):
    cipher = Cipher(algorithms.AES(key), modes.GCM(iv, tag))
    decryptor = cipher.decryptor()
    return decryptor.update(ciphertext) + decryptor.finalize()

# ECDH 키 교환 및 KDF (X9.63-KDF with SHA-256)
def derive_shared_key(private_key, peer_public_key):
    shared_secret = private_key.exchange(ec.ECDH(), peer_public_key)
    print(f"shared key : {shared_secret.hex()}")
    kdf = X963KDF(algorithm=SHA256(), length=32, sharedinfo=None)  # 256-bit AES key
    return kdf.derive(shared_secret)

# 🔹 1️⃣ Alice와 Bob의 키 쌍 생성 (SECP256R1 사용)
alice_private_key = ec.generate_private_key(ec.SECP256R1())
bob_private_key = ec.generate_private_key(ec.SECP256R1())

alice_public_key = alice_private_key.public_key()
bob_public_key = bob_private_key.public_key()

# 🔹 2️⃣ Alice가 Bob의 공개 키를 받아 대칭 키 생성
alice_shared_key = derive_shared_key(alice_private_key, bob_public_key)

# 🔹 3️⃣ Bob이 Alice의 공개 키를 받아 같은 대칭 키 생성
bob_shared_key = derive_shared_key(bob_private_key, alice_public_key)

assert alice_shared_key == bob_shared_key  # 키가 동일해야 함

# 🔹 4️⃣ Alice가 메시지를 암호화하여 Bob에게 전송
plaintext = b"Hello"
iv, ciphertext, tag = aes_gcm_encrypt(alice_shared_key, plaintext)

# 🔹 5️⃣ Bob이 받은 데이터를 복호화
decrypted_message = aes_gcm_decrypt(bob_shared_key, iv, ciphertext, tag)

print(f"📩 암호화된 메시지: {ciphertext.hex()}")
print(f"🔓 복호화된 메시지: {decrypted_message.decode()}")

1. alice & bob은 secp256r1 곡선으로 키 쌍 생성

2. alice/bob 개인키와 bob/alice 공개키로 ECDH 수행하여 공유키 유도

3. 공유키를 키 유도(X.963-SHA256)하여 공유 AES 대칭키 유도

4. 공유 AES 대칭 키로 AES-GCM 수행

곡선 알고리즘 사용 사례 특징
secp256r1 ECDSA 범용 (NIST 추천) 속도 느림
secp256k1 ECDSA 블록체인 속도 느림
Ed25519 EdDSA SSH 속도 빠름 / 공개키 : 256바이트 (고정 크기)

# secp256k1 예시

from ecdsa import SECP256k1, SigningKey, VerifyingKey
from ecdsa.util import sigencode_der, sigdecode_der
import hashlib

# Alice (서명자)
def alice_sign(message):
    # Alice의 개인키 생성
    sk = SigningKey.generate(curve=SECP256k1)
    # Alice의 공개키 생성
    vk = sk.get_verifying_key()
    
    # 메시지 해싱
    message_hash = hashlib.sha256(message.encode('utf-8')).digest()
    print(f"Alice가 해싱한 메시지: {message_hash.hex()}")
    
    # 서명 생성
    signature = sk.sign(message_hash, sigencode=sigencode_der)
    print(f"Alice의 서명: {signature.hex()}")
    
    return signature, vk

# Bob (검증자)
def bob_verify(message, signature, vk):
    # 메시지 해싱
    message_hash = hashlib.sha256(message.encode('utf-8')).digest()
    print(f"Bob이 해싱한 메시지: {message_hash.hex()}")
    
    # 서명 검증
    try:
        vk.verify(signature, message_hash, sigdecode=sigdecode_der)
        print("서명 검증 성공!")
        return True
    except:
        print("서명 검증 실패!")
        return False

# Alice가 서명
message = "Alice의 중요한 메시지"
print(f"서명할 메시지: {message}")
signature, alice_vk = alice_sign(message)

# Bob이 서명 검증
bob_verify(message, signature, alice_vk)
서명할 메시지: Alice의 중요한 메시지
Alice가 해싱한 메시지: 2491722cc10f5bd7bc9f79ae476ba2c1055dab43be2fca9dc81e0718a1381642
Alice의 서명: 3044022029160eb2534be33a8311639465202dcdee5a7725fc41cd9f01e1c8d986a66688022003c159499de24335b0c89d4a34cc35b0714b58d935ed615cc131b1ab2278d7ad
Bob이 해싱한 메시지: 2491722cc10f5bd7bc9f79ae476ba2c1055dab43be2fca9dc81e0718a1381642
서명 검증 성공!

서명 구조 (der)

SEQUENCE 태그, 서명 구조의 시작 30
서명 길이 44
 r의 INTEGER 태그 02
r의 길이 20 (0x20)
r 값  29 16 0E B2 53 4B E3 3A 83 11 63 94 65 20 2D CD EE 5A 77 25 FC 41 CD 9F 01 E1 C8 D9 86 A6 66 88
s의 INTEGER 태그 02
s의 길이 20 (0x20)
s 값 03 C1 59 49 9D E2 43 35 B0 C8 9D 4A 34 CC 35 B0 71 4B 58 D9 35 ED 61 5C C1 31 B1 AB 22 78 D7 AD

# secp256r1 예시

from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
import hashlib

# Alice (서명자)
def alice_sign(message):
    # Alice의 개인키 생성 (secp256r1 사용)
    sk = ec.generate_private_key(ec.SECP256R1())
    
    # Alice의 공개키 생성
    vk = sk.public_key()
    
    # 메시지 해싱
    message_hash = hashlib.sha256(message.encode('utf-8')).digest()
    print(f"Alice가 해싱한 메시지: {message_hash.hex()}")
    
    # 서명 생성
    signature = sk.sign(message_hash, ec.ECDSA(hashes.SHA256()))
    print(f"Alice의 서명: {signature.hex()}")
    
    return signature, vk

# Bob (검증자)
def bob_verify(message, signature, vk):
    # 메시지 해싱
    message_hash = hashlib.sha256(message.encode('utf-8')).digest()
    print(f"Bob이 해싱한 메시지: {message_hash.hex()}")
    
    # 서명 검증
    try:
        vk.verify(signature, message_hash, ec.ECDSA(hashes.SHA256()))
        print("서명 검증 성공!")
        return True
    except:
        print("서명 검증 실패!")
        return False

# Alice가 서명
message = "Alice의 중요한 메시지"
print(f"서명할 메시지: {message}")
signature, alice_vk = alice_sign(message)

# Bob이 서명 검증
bob_verify(message, signature, alice_vk)
서명할 메시지: Alice의 중요한 메시지
Alice가 해싱한 메시지: 2491722cc10f5bd7bc9f79ae476ba2c1055dab43be2fca9dc81e0718a1381642
Alice의 서명: 304402202797f1bd7f59f0f2a7865655fd2999ca1d1e5158b29d546cb71aa57155ab901502201165c74887c2ad384c9f8cf6a7b4de771c4bd06467bf396422bcee39527b60d4
Bob이 해싱한 메시지: 2491722cc10f5bd7bc9f79ae476ba2c1055dab43be2fca9dc81e0718a1381642
서명 검증 성공!

서명 구조가 secp256k1과 동일

# ed25519 예시

from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives import hashes
import hashlib

# Alice (서명자)
def alice_sign(message):
    # Alice의 개인키 생성 (ed25519 사용)
    sk = ed25519.Ed25519PrivateKey.generate()
    
    # Alice의 공개키 생성
    vk = sk.public_key()
    
    # 메시지 해싱
    message_hash = hashlib.sha256(message.encode('utf-8')).digest()
    print(f"Alice가 해싱한 메시지: {message_hash.hex()}")
    
    # 서명 생성
    signature = sk.sign(message_hash)
    print(f"Alice의 서명: {signature.hex()}")
    
    return signature, vk

# Bob (검증자)
def bob_verify(message, signature, vk):
    # 메시지 해싱
    message_hash = hashlib.sha256(message.encode('utf-8')).digest()
    print(f"Bob이 해싱한 메시지: {message_hash.hex()}")
    
    # 서명 검증
    try:
        vk.verify(signature, message_hash)
        print("서명 검증 성공!")
        return True
    except:
        print("서명 검증 실패!")
        return False

# Alice가 서명
message = "Alice의 중요한 메시지"
print(f"서명할 메시지: {message}")
signature, alice_vk = alice_sign(message)

# Bob이 서명 검증
bob_verify(message, signature, alice_vk)
서명할 메시지: Alice의 중요한 메시지
Alice가 해싱한 메시지: 2491722cc10f5bd7bc9f79ae476ba2c1055dab43be2fca9dc81e0718a1381642
Alice의 서명: 1a9e8142f0ca566e3bdb67330816c7592c2882d3c3ccd154d5c29c7795aabdc82271aa22370d64adcc1eedb868f9448d25fdbf407b145dda90ba08d8cf29fa00
Bob이 해싱한 메시지: 2491722cc10f5bd7bc9f79ae476ba2c1055dab43be2fca9dc81e0718a1381642
서명 검증 성공!

서명 구조

r (32바이트) 1a9e8142f0ca566e3bdb67330816c7592c2882d3c3ccd154d5c29c7795aabdc8
s (32바이트) 2271aa22370d64adcc1eedb868f9448d25fdbf407b145dda90ba08d8cf29fa00

https://github.com/codetronik/optee-aes

1. 키 설정

TA에서는 OP-TEE API를 활용하여 eMMC의 RPMB(Replay Protected Memory Block) 파티션에 키를 생성하고 삭제할 수 있다. 이 영역은 Normal World에서 접근할 수 없다.

별칭(alias)을 지정하여 키에 접근한다. (TA간 키는 공유할 수 없다. 즉, alias가 동일하더라도, 다른 TA의 alias에 접근할 수 없다.) RPMB에 키가 존재하지 않으면, 키를 생성하여 저장한다. 

TA 관련 주요 API들은 중요 데이터 저장을 위해 세션을 제공한다. 뭘 저장할 지는 자유이며, 필자는 이 곳에 키를 저장하였다.

2. AES-GCM을 구현

세션에서 키를 불러온 후, 이를 사용하여 데이터를 암/복호화한다. TA에서는 암호화 과정에서 IV를 랜덤하게 생성하며, 최종적으로 생성된 태그(tag)와 암호문(cipher)을 함께 반환한다.

소스 : https://github.com/codetronik/optee_example

프로젝트 구조는 아래와 같이 구성되어야 한다. (어떻게 만들던 상관없지만, Normal 과 TA는 분리되어 있어야 개발이 편해진다.)

├── include
│   └── common.h
├── normal
│   └── main.cpp
└── ta
    ├── Makefile
    ├── ta.c 
    ├── sub.mk // 필수 파일
    └── user_ta_header_defines.h // 필수 파일

유저가 OP-TEE OS의 Normal World(일반 리눅스 영역)에서 main을 실행하면, Secure World의 TA와 통신하게 된다.

TA 소스는 콜백 함수 구현이므로, 반드시 C로 작성하여야 컴파일이 된다. Normal은 C++로 작성해도 상관 없다. 

TA와 Normal 각각 컴파일 하여야 한다.

필자는 라즈베리파이를 사용 중이라 크로스컴파일러 설치를 안했으므로, 참고 바람.

normal의 경우 필자는 clang을 사용했다.

// normal
clang --sysroot=/home/code/optee/out-br/host/aarch64-buildroot-linux-gnu/sysroot -o main main.cpp -lteec -std=c++20 -lstdc++ -Wunused-parameter
// TA
make

TA 실행 파일(11223344-5566-7788-99aa-bbccddeeff00.ta)은 /lib/optee_armtz에 복사한다. Normal은 /tmp 등 적절한 곳에 복사한다. 우분투<->QEMU간 파일 전송은 #1편을 참조

Secure World 콘솔을 보면, Hello 가 로깅된 것을 확인할 수 있다.

참조 : https://optee.readthedocs.io/en/latest/building/trusted_applications.html

목표 : qemu에 op-tee os를 설치한 후 테스트

필자 환경 : ubuntu 24.04.2 (라즈베리파이)

sudo apt update
sudo apt upgrade
sudo apt install -y adb acpica-tools autoconf automake bc bison build-essential ccache cpio cscope curl device-tree-compiler e2tools expect fastboot flex ftp-upload gdisk git libattr1-dev libcap-ng-dev libfdt-dev libftdi-dev libglib2.0-dev libgmp3-dev libhidapi-dev libmpc-dev libncurses5-dev libpixman-1-dev libslirp-dev libssl-dev libtool libusb-1.0-0-dev make repo mtools ninja-build python3-cryptography python3-pip python3-pyelftools python3-serial python-is-python3 rsync swig unzip uuid-dev wget xdg-utils xsltproc xterm xz-utils zlib1g-dev

mkdir -p ~/optee && cd ~/optee

git config --global user.email "1.com"
git config --global user.name "1"

repo init -u https://github.com/OP-TEE/manifest.git -m qemu_v8.xml -b 4.5.0
repo sync -j16 --no-clone-bundle

cd build
make -j16 toolchains

make -j16 #크로스 컴파일
make run #op-tee os 구동

make run-only # 2번째 실행부터는 이 명령어로 접속

화면이 뜨면 c 입력

 

Normal World에서 root 입력

 

예제 테스트

공유 폴더 설정하는 방법

[호스트]

vi /home/code/optee/build/Makefile

QEMU_RUN_ARGS 문자열 검색 후 아래 추가 (path는 본인 경로에 맞게)

QEMU_RUN_ARGS += -fsdev local,id=fsdev0,path=/home/code,security_model=mapped,multidevs=remap -device virtio-9p-pci,fsdev=fsdev0,mount_tag=hostshare

 

[OP-TEE OS]

mkdir -p /mnt/host
mount -t 9p -o trans=virtio hostshare /mnt/host

필자 구매 품목 (추천!)

  • 라즈베리파이 5 16GB
  • PCIE to M.2 HAT (2340 규격)
  • M.2 NVMe 2340 128GB
  • M.2 NVMe 외장 케이스
  • Micro HDMI to HDMI 변환기
  • 5V 5A 어댑터 (필수)

1. PC에 M.2 USB장착

2. Raspberry Pi Imager 다운로드 및 실행. 라즈베리파이 OS 선택 후 설치 (전력 문제로 우분투 설치는 추천하지 않음. 마우스가 먹통이 되거나, 와이파이 연결이 안됨)

3. 라즈베리파이에 M.2 장착 후 부팅

4. $sudo vi /boot/firmware/config.txt

dtparam밑에 dtparam=pciex1_gen3 추가

 

 

Kyber는 키 캡슐화 메커니즘으로, 쉽게 설명하면 공유 키(AES)를 유도할때 사용한다고 보면 된다.

Kyber의 보안 강도는 아래와 같다.

Kyber-512 = AES-128

Kyber-768 = AES-192

Kyber-1024 = AES-256

매개변수 세트 공개키 사이즈 개인키 사이즈 암호문 사이즈 공유키 사이즈
Kyber512 800 바이트 1632 바이트 768 바이트 32 바이트
Kyber768 1184 바이트 2400 바이트 1088 바이트 32 바이트
Kyber1024 1568 바이트 3168 바이트 1568 바이트 32 바이트

 

테스트 코드 : https://github.com/pq-crystals/kyber 빌드 후, test_vectors를 실행

*공식에서는 Kyber768 사용을 권장하지만, 귀찮아서 그냥 Kyber512로 진행하였음

1. Bob이 공개 키와 비밀 키를 생성

Public Key: c29ac66c84bee3f129508c2b8c790c99a5ca41e5707e9b8c75c04d7ea8a481980a358b066a4a7e28d15d10374f75c33da6029cd490746fb55f5feab2ce823dec1830c0c18ef89ba3cc3bce4d252a07a40d401a4c8d273618b595db21ca4a959eb4d133556801b2b78254b2b5955c0400962dbb5a487aaa24a430b614e2af9338afd4b0339bd830a9cb761db1a83220352dd523b8a583022ca13e246506548c57ba3850ac5c50d864e2d48b89694277cc7a8174ad7b1ba2ee621d57d29b23c22df831872051145d2535dbb025e29c6da38cb475958e2a8808a431bed5b486821a1513a729cd979b6c8b382503cf53337616e1059ddc59977219d2f17b32acabbe86c468c1267b2b862ac565a7e232266c83fc700cda19b616377389428e62614cd6ac9f08fb12d21827feb324b14bc16cc0c20904b3973b9dfe60af577776449ac34eb00989e5a876143bc9b930a3c2a5bb861208f225dd97625bb36b2d8810d0452e458968b90c6a6d97c2dfca7341d53c741a60e2b91385c86bb3b1be5f10708c546ae6318209ba268dd2b4e3e4722761491ae215600248e7541e6080b865f44a169c02a5b374f1fa5502333753979c9da75452c4814a8b8fd682b8e0370699296bc2f42d38e5a2de92c5f5f61f24b65e1b9b75249b8759708706640000b490937683e1ccbbf39a0baecb1edd62826721524bcc4d3bf06f8e5ab368aa426eb42c701839e8bbcc69dbccd2757f84c60a409b6629d98dc92947367c52f0698c3c41c01110bafbeb0621cc175170375f8250c0f62406e32e10725b47e3c165845a7ada8fb2c55555f5cc8602246fe06f875a6eb5c9459dd19292428492a76738b8057e84c8e11436c4eb788e494e3952657ed331a2e4a47d75492365c473f484200502868c733bb9b2b3e44af2c98adfb91a4e1a144eec5a32d24f13c78775f206d7a94dee12007f778e484a1430666bfeda6dbb31b757d72b5c79a469522fe6599abb45b52cc6403c4970f65684bb770ca78893ba439057013655309cd84c524c9ca558e3612041b7b2026e2187598afb46f1d4ca85096dbc9bcc1c25779dfb607052e11649bb7f5f7268f979c4d8140afe6ce53830f38602290d751427f07b27
Secret Key: 7cf108c75a4d3592053d0ca79ce527ec1734f7023656e26253e2bfc68960dea73d28d7a9821597b48b4504837e27132c8ebc48505303aeb568f9d1928f7244cf98b4a88843c5db69845abfc4e40683dca3bde694445c63cc512bd2e4608e91a5697738bbca3b09a98da49757ad65c085125d11d01178d15acb251f417cbeff2a2ac1b05dc70839ffb297be205152e98371745de76243d3a302dfda7f16f5a8f0d2b73021a7f5c0490ff6b5a4125843889364288bede430835cce5bf8b86377132aea3ced911311a43b87e10ae471b49f1a31b636ce5d7c415d7c17539575724c3166ab23ca183f9962a0b17190f3dc204dc2551eec234b7c4e298a4e60f15d4e40bcaf1ba0eaa806e214bda0a0b0e0f51b34745e148290e222a4496c946766029cd82964429fd85a30ee3c0c6dea4e6bc840237c38d8e9b6a893702444bfeef783a104a8b46b8309a914cbaaa8cec9c08bb54a3cfc1a22c5a9d1b87685a30417d846d5e22242e8c0c8316cb7f15832b70b4bbc453bb67485e34c87d9a2d4b294d257a98d864afab445aea6bf4830404d170ca7484cc799b73ae3ce375c3a13d1318bd29158620328c8bc22d812d269c8ec133ce4f977bd95300054b5ef246bb086a6d3340575464183e10db1a126f81a43d2f800e962568de3411515b90dc1256446cf8fc33149e66a8657c221335eb57a8ca6262b06981a032823222c9da22835271033212b4e9d516132a428709b5882ab8764771832968dc73c4cd241adb145b5e654b38bab03e3524f113525dd0a63e8f195fceb26b8b03063c4863459cc10c5884cac016eebb7afa2519b27293b845e7e893e70bb21d0e004f1d05015dc71fcf6b150c750aa98c96f89c8da199eefc1712c409bc833a84d404ad72c873bf910c9190645b94dd2a31347596029d22abd071f5387588a9917fee4b33d1bbcfa1858390662b656c09ff824ed177abf44a118b7c78bba96b9f9b5a3a54e597829be686868e5463f99be58da0be7886501730e01e26aad0535896616d98125c38b3eb778114176b1bd498ebd92b5bd0a98a0a39f77b599c3e63e66fb62167b06c29ac66c84bee3f129508c2b8c790c99a5ca41e5707e9b8c75c04d7ea8a481980a358b066a4a7e28d15d10374f75c33da6029cd490746fb55f5feab2ce823dec1830c0c18ef89ba3cc3bce4d252a07a40d401a4c8d273618b595db21ca4a959eb4d133556801b2b78254b2b5955c0400962dbb5a487aaa24a430b614e2af9338afd4b0339bd830a9cb761db1a83220352dd523b8a583022ca13e246506548c57ba3850ac5c50d864e2d48b89694277cc7a8174ad7b1ba2ee621d57d29b23c22df831872051145d2535dbb025e29c6da38cb475958e2a8808a431bed5b486821a1513a729cd979b6c8b382503cf53337616e1059ddc59977219d2f17b32acabbe86c468c1267b2b862ac565a7e232266c83fc700cda19b616377389428e62614cd6ac9f08fb12d21827feb324b14bc16cc0c20904b3973b9dfe60af577776449ac34eb00989e5a876143bc9b930a3c2a5bb861208f225dd97625bb36b2d8810d0452e458968b90c6a6d97c2dfca7341d53c741a60e2b91385c86bb3b1be5f10708c546ae6318209ba268dd2b4e3e4722761491ae215600248e7541e6080b865f44a169c02a5b374f1fa5502333753979c9da75452c4814a8b8fd682b8e0370699296bc2f42d38e5a2de92c5f5f61f24b65e1b9b75249b8759708706640000b490937683e1ccbbf39a0baecb1edd62826721524bcc4d3bf06f8e5ab368aa426eb42c701839e8bbcc69dbccd2757f84c60a409b6629d98dc92947367c52f0698c3c41c01110bafbeb0621cc175170375f8250c0f62406e32e10725b47e3c165845a7ada8fb2c55555f5cc8602246fe06f875a6eb5c9459dd19292428492a76738b8057e84c8e11436c4eb788e494e3952657ed331a2e4a47d75492365c473f484200502868c733bb9b2b3e44af2c98adfb91a4e1a144eec5a32d24f13c78775f206d7a94dee12007f778e484a1430666bfeda6dbb31b757d72b5c79a469522fe6599abb45b52cc6403c4970f65684bb770ca78893ba439057013655309cd84c524c9ca558e3612041b7b2026e2187598afb46f1d4ca85096dbc9bcc1c25779dfb607052e11649bb7f5f7268f979c4d8140afe6ce53830f38602290d751427f07b27cda93dec4c4dc4d8484457fd882399c4b918c49fa8389a1dfa8c9f92f39b00cf3cb1eea988004b93103cfb0aeefd2a686e01fa4a58e8a3639ca8a1e3f9ae57e2

2. Alice는 Bob의 공개 키를 사용하여 공유 키를 유도하고, 이를 캡슐화 함

Ciphertext: 5a645120b878936d202efc4851f38e6bb6573c3b14b0b9bb44bf372d8b1aa8034a9f1a1584076f0a38e89a9d49a50b792ace7584981be8e239272deef914418fefe2dad97dc0ec20cfe8a9599b9bbe3ecce91f97e10cd9ef2c4950e3ea3c46fe481eb0d24878c4624ad344f0dc9863e7d170937a8cecc6f7d00f9565529d572959cc49d0f7042ff43b7d1d71efd22f2654e14e78c31f34a26ae53b067ae0380a65a732459503da5e9406d50a70e3d5ebdbf3c9c01cad1cc001ebe69e6cff20e64ce5c802b691587e404cf6efa2799a2ffd353492a75f0e2ea52a974e0545a086a3bd14b69045238140a7200b10c3276cc6b2a67c173f7c1ad64545adb8ebdf7835e9aa1f54f6891369988f3625c45f2fec8d9a07b911d32ba69d9ff5d74f10a6808b25a3c81709945bf213c3450d74481f065042186b0d36fb55271162dfaf41e516a408f83ccabe8a0ba7effa16f88f6d7dbdb64e608c8f18d686c7e5d548d737116fa562dc76e7994a86374a9c85b8b17c4f025fa23a4de1a997a87e5a65f5c5386772491fd8d10731f5f5aa60366ffe3fd209cb7b7a8615320ad0728f41e812bd88d2d6104753917e89e1ca0f10177cf5dab040e466908b27446215709b0912972c428c4d9aad9432d9a159069c96154001cb0be4de597e9871b04bddaa4539f838bc12ab0a3ea7e8c8481bcdfcc1834369fcf061f7c599efdc4f6c434102991446aea12881e163fd4ee6c458b82e42759f8b11b0612c12d5a777acf4c7cdd26fb7da0b9098dc4af94704daa529945ab169cdb22d3966fcd26950e2418cac9bc7dc32c4a604f368f0f8a9c7ddce8b5e476b26b33116d607df1b49c205ada0d2ea5a5a64eecb22549ddf18a0daed2e5d44cb6174b9781236eee11f95ab0c45836bcafc73af3bec11440bc1c605669eb019cfac0097943cf29bbffce0f823293da623e5fa6d2a7ee0c7b4507596a62ef46bbe4e1b63cc96ba9878a7b39f84b59dd336f1659a24cbb33015d515e9e80e3e7902b1d583f8ee97153cd8ba1fadeb9ee7e2f2c23dfee85a50d5c3554b79922a4537d6dc4f09418dfdd744596cbf68
Shared Key: 221d7d86011659313c83ce3fd0ab26797ef217e11d1f0bc76e7952fbe52a0a58

3. Bob은 Alice가 보낸 캡슐화된 키를 자신의 비밀 키로 복호화하여 Alice와 동일한 공유키를 얻음

Shared Key: 221d7d86011659313c83ce3fd0ab26797ef217e11d1f0bc76e7952fbe52a0a58

 

Kyber 공식 홈페이지에서는 하이브리드를 권장한다. 예) Kyber+ECDH
키 교환에 대해서는 아래를 참조
https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-12.html

 

만약 크롬을 사용중이라면, 아래에 접속하여 TLS 1.3 kyber 사용을 활성화 할 수 있다.

 

 

1. 환경 설정 (wsl 기준)

$ git clone https://github.com/emscripten-core/emsdk.git
$ cd emsdk
$ ./emsdk install latest
$ ./emsdk activate latest
$ source ./emsdk_env.sh
$ emcc --version

2. hello.c 작성

#include <stdio.h>

int main() {
    printf("Hello World\n");
    return 0;
}

3. 컴파일

emcc hello.c -o hello.html

4. 서버 구동

npx http-server ~ -o -p 9999


참고

https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install

https://emscripten.org/docs/tools_reference/emcc.html#emccdoc

https://developer.mozilla.org/ko/docs/WebAssembly/C_to_Wasm


알아낸 것 1. 샌드 박스 내부는 리눅스 스타일로 구성되어 있음. 아래는 직접 돌려본 예시

/tmp
/home
/home/web_user
/dev
/dev/null
/dev/tty
/dev/tty1
/dev/random
/dev/urandom
/dev/shm
/dev/shm/tmp
/dev/stdin
/dev/stdout
/dev/stderr
/proc
/proc/self
/proc/self/fd
/proc/self/fd/0
/proc/self/fd/1
/proc/self/fd/2
/proc/self/fd/3
/proc/self/fd/4
/proc/self/fd/5
/proc/self/fd/6

알아낸 것  2. C코드로 디컴파일 가능

LLVM 기반이기 때문에 OLLVM 개발 가능

https://github.com/HakonHarnes/emcc-obf

알아낸 것  3. int main()의 주소는 0x1

이것은 전형적인 메모리 레이아웃은 아님

+ Recent posts