3/31/2020

ECDSA 기반의 Key 및 Certificate 분석

1. ECDSA 기반의 Key 와 Certificate 분석 

ECDSA(Elliptic Curve Digital Signature Algorithm)으로 주로 Digital Signature에서 사용되어지며,
이곳에서도 ECDSA 기반의 Certificate 생성 및 분석한다.
ECDSA는 기본적으로 ECC(Elliptic Curve Cryptography)기반의 Private Key/Public Key 기반으로 동작되어진다. 
ECDSA 와 RSA를 비교하면, RSA 비하여 속도가 빠르다고 하며 암호화 용량이 적어 요즘  많이 사용되어진다고 한다. 
특히, 임베디드에서는 빠르고, 적은용량으로 고효율을 요구하기 때문이다. 


아래에서 각 기본 개념들을 이해해보록하자. 

ECC(Elliptic Curve Cryptography)
한글로 번역하면, 타원곡선 암호화이며 관련자료들을 이해해보자.

EC(Elliptic Curve)
ECC를 세부이해하기 위해서 타원곡선이 어떻게 동작하는지 알아보자
RSA-3072bit (384 bytes) 와 ECC-256 bit (32 bytes) 동일급 하며, 아래 링크설명이 너무 좋다.

ECDSA(Elliptic Curve Digital Signature Algorithm)
ECC기반으로 생성된 Digital Signature 알고리즘으로 인증서 내부에 존재함 
  https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm

Elliptic-curve Diffie–Hellman (ECDH)  
Cipher Suite 키교환알고리즘

TLS 와 SSL의 관련지원사항 및 기본구조확인

전체구성을 알고 싶다면 아래참고


ECDSA기반으로 Certificate를 많이 구성하고 사용하는데, 이 기본구조를 알고자 아래와 같이 세부적으로 분석한다.
그리고 더불어 CA기반의 Certificate의 세부구성도 분석하도록 한다. 

Certificate의 전체구성을 알고자하면 바로 3. Cerficiate Auhtority의 동작을 확인 후 세부적으로 분석하자.

1.1 OpenSSL 기본 지원사항 확인

OpenSSL의 기본지원사항들을 확인해보도록 하자. 

  • OpenSSL 의 기본정보확인
  1. OpenSSL Version 확인 
  2. ECDSA의 Curves List 확인 

$ openssl version
OpenSSL 1.1.1b  26 Feb 2019

//ECDSA Key의  동작확인 및 ECDSA List 
$ openssl ecparam -list_curves // 모든 지원 curves 확인 secp xxx Key Size 
  secp112r1 : SECG/WTLS curve over a 112 bit prime field
  secp112r2 : SECG curve over a 112 bit prime field
  secp128r1 : SECG curve over a 128 bit prime field
  secp128r2 : SECG curve over a 128 bit prime field
  secp160k1 : SECG curve over a 160 bit prime field
  secp160r1 : SECG curve over a 160 bit prime field
  secp160r2 : SECG/WTLS curve over a 160 bit prime field
  secp192k1 : SECG curve over a 192 bit prime field
  secp224k1 : SECG curve over a 224 bit prime field
  secp224r1 : NIST/SECG curve over a 224 bit prime field
  secp256k1 : SECG curve over a 256 bit prime field           //현재 secp256r1 와 다름 주의 
  secp384r1 : NIST/SECG curve over a 384 bit prime field
  secp521r1 : NIST/SECG curve over a 521 bit prime field
  prime192v1: NIST/X9.62/SECG curve over a 192 bit prime field
  prime192v2: X9.62 curve over a 192 bit prime field
  prime192v3: X9.62 curve over a 192 bit prime field
  prime239v1: X9.62 curve over a 239 bit prime field
  prime239v2: X9.62 curve over a 239 bit prime field
  prime239v3: X9.62 curve over a 239 bit prime field
  prime256v1: X9.62/SECG curve over a 256 bit prime field            //현재 secp256r1 동일(이름이 변경됨) 
  sect113r1 : SECG curve over a 113 bit binary field
  sect113r2 : SECG curve over a 113 bit binary field
  sect131r1 : SECG/WTLS curve over a 131 bit binary field
  sect131r2 : SECG curve over a 131 bit binary field
  sect163k1 : NIST/SECG/WTLS curve over a 163 bit binary field
  sect163r1 : SECG curve over a 163 bit binary field
  sect163r2 : NIST/SECG curve over a 163 bit binary field
  sect193r1 : SECG curve over a 193 bit binary field
  sect193r2 : SECG curve over a 193 bit binary field
  sect233k1 : NIST/SECG/WTLS curve over a 233 bit binary field
  sect233r1 : NIST/SECG/WTLS curve over a 233 bit binary field
  sect239k1 : SECG curve over a 239 bit binary field
  sect283k1 : NIST/SECG curve over a 283 bit binary field
  sect283r1 : NIST/SECG curve over a 283 bit binary field
  sect409k1 : NIST/SECG curve over a 409 bit binary field
  sect409r1 : NIST/SECG curve over a 409 bit binary field
  sect571k1 : NIST/SECG curve over a 571 bit binary field
  sect571r1 : NIST/SECG curve over a 571 bit binary field
  c2pnb163v1: X9.62 curve over a 163 bit binary field
  c2pnb163v2: X9.62 curve over a 163 bit binary field
  c2pnb163v3: X9.62 curve over a 163 bit binary field
  c2pnb176v1: X9.62 curve over a 176 bit binary field
  c2tnb191v1: X9.62 curve over a 191 bit binary field
  c2tnb191v2: X9.62 curve over a 191 bit binary field
  c2tnb191v3: X9.62 curve over a 191 bit binary field
  c2pnb208w1: X9.62 curve over a 208 bit binary field
  c2tnb239v1: X9.62 curve over a 239 bit binary field
  c2tnb239v2: X9.62 curve over a 239 bit binary field
  c2tnb239v3: X9.62 curve over a 239 bit binary field
  c2pnb272w1: X9.62 curve over a 272 bit binary field
  c2pnb304w1: X9.62 curve over a 304 bit binary field
  c2tnb359v1: X9.62 curve over a 359 bit binary field
  c2pnb368w1: X9.62 curve over a 368 bit binary field
  c2tnb431r1: X9.62 curve over a 431 bit binary field
  wap-wsg-idm-ecid-wtls1: WTLS curve over a 113 bit binary field
  wap-wsg-idm-ecid-wtls3: NIST/SECG/WTLS curve over a 163 bit binary field
  wap-wsg-idm-ecid-wtls4: SECG curve over a 113 bit binary field
  wap-wsg-idm-ecid-wtls5: X9.62 curve over a 163 bit binary field
  wap-wsg-idm-ecid-wtls6: SECG/WTLS curve over a 112 bit prime field
  wap-wsg-idm-ecid-wtls7: SECG/WTLS curve over a 160 bit prime field
  wap-wsg-idm-ecid-wtls8: WTLS curve over a 112 bit prime field
  wap-wsg-idm-ecid-wtls9: WTLS curve over a 160 bit prime field
  wap-wsg-idm-ecid-wtls10: NIST/SECG/WTLS curve over a 233 bit binary field
  wap-wsg-idm-ecid-wtls11: NIST/SECG/WTLS curve over a 233 bit binary field
  wap-wsg-idm-ecid-wtls12: WTLS curve over a 224 bit prime field
  Oakley-EC2N-3:
        IPSec/IKE/Oakley curve #3 over a 155 bit binary field.
        Not suitable for ECDSA.
        Questionable extension field!
  Oakley-EC2N-4:
        IPSec/IKE/Oakley curve #4 over a 185 bit binary field.
        Not suitable for ECDSA.
        Questionable extension field!
  brainpoolP160r1: RFC 5639 curve over a 160 bit prime field
  brainpoolP160t1: RFC 5639 curve over a 160 bit prime field
  brainpoolP192r1: RFC 5639 curve over a 192 bit prime field
  brainpoolP192t1: RFC 5639 curve over a 192 bit prime field
  brainpoolP224r1: RFC 5639 curve over a 224 bit prime field
  brainpoolP224t1: RFC 5639 curve over a 224 bit prime field
  brainpoolP256r1: RFC 5639 curve over a 256 bit prime field
  brainpoolP256t1: RFC 5639 curve over a 256 bit prime field
  brainpoolP320r1: RFC 5639 curve over a 320 bit prime field
  brainpoolP320t1: RFC 5639 curve over a 320 bit prime field
  brainpoolP384r1: RFC 5639 curve over a 384 bit prime field
  brainpoolP384t1: RFC 5639 curve over a 384 bit prime field
  brainpoolP512r1: RFC 5639 curve over a 512 bit prime field
  brainpoolP512t1: RFC 5639 curve over a 512 bit prime field
  SM2       : SM2 curve over a 256 bit prime field

관련내용
  https://crypto.stackexchange.com/questions/33052/is-there-any-difference-between-nist-and-secp-curves-in-terms-of-their-algorithm
  https://crypto.stackexchange.com/questions/70889/is-curve-p-384-equal-to-secp384r1


2. ECDSA Certificate 생성방법 

ECDSA 기반의 Key 기반으로 Certificate를 생성하는 방법으로 아래 방법으로 간단히 생성이 가능하다.

  • ECDSA 기반의 Certifiace 생성
  1. ECDSA Private Key 생성방법 
  2. ECDSA Private Key 기반의 Certificate 생성

$ openssl ecparam -out key.pem -name secp256r1 -genkey  // Private Key 와 Public Key 생성 

$ openssl req -new -key key.pem -x509 -nodes -days 365 -out cert.pem  // Key 기반으로 Certificate 생성(1년) 

상위와 같이 Private Key 기반으로 쉽게 Certificate를 생성가능
  1. Private Key(key.pem) 생성 
  2. Cerfiticate(cert.pem)  생성완료  (X.509)

아래 링크 생성방법과 동일
  https://stackoverflow.com/questions/11992036/how-do-i-create-an-ecdsa-certificate-with-the-openssl-command-line
  https://zurgl.com/how-to-create-an-ecdsa-certificate/
  https://stackoverflow.com/questions/11992036/how-do-i-create-an-ecdsa-certificate-with-the-openssl-command-line


ECC Key 생성과 Certificate는 기본구조 세부분석으로 알고 싶지 않다면 , 아래는 보지말고, 그냥 위 Command로만 생성하고 말자.

  • ECDSA 기반의 Certificate 분석할 것
아래의 3부분은 상위에서 만든 Private Key와 Certificate를 기본구조 이해하기 위해 분석하는것이므로 알고 이해했다면 넘어가자.

  2.1 ECSDSA Private Key 생성 및 분석: Private Key 내부구성 및 분석방법
  2.2 ECSDSA Certificate Signature 분석: Certificate의 Signature의 구성 및 사용방법 
  2.2 ECSDSA Certificate 분석: Certificate 생성방법 및 분석방법 

  • 실제 Certificate의 구성분석 
상위를 분석한 후 CA(Cerficiate Autority)의 기본동작을 보도록하자. 
  3. Certificate Auhoirty 기본동작 


2.1 ECDSA의 Private Key 생성 및 분석

Eliptic-curve cryptography 로 Private Key 생성과 분석이므로 분석할 필요가 없다면 넘어가자
**ECDSA Private Key 비대칭 Key이니, 당연히 이 정보 안에 Private Key와 Public Key 정보도 같이 포함되어있다.

ECDSA는 Certifcate에서 사용되어지는 Signature 알고리즘이니, 정확히 말하면, ECDSA가 아니라 ECC(Elliptic Curve Cryptography)의 PrivateKey가 맞겠다.  

더불어 생성된 Key 정보를 OpenSSL에서 제공하는 다양한 명령어로 분석해보자 

  • A. ECDSA Private Key 생성방법 
OpenSSL에서 지원되는 Curve List에서 각 이름별로 Key 생성 
// base64 Encoding에서 아래부분을 반드시 확인하며, 각각 의미를 확인
//-----BEGIN EC PRIVATE KEY-----
//-----END EC PRIVATE KEY----- 

$ openssl ecparam -out key0.pem -name secp256r1 -genkey  // ECDSA P-256 (secp256r1 Curve) 사용 
using curve name prime256v1 instead of secp256r1   // secp256r1 이 prime256v1 대체됨  
$ cat key0.pem                                     // Text기반으로 보기때문에 Base64 Encoding 이됨  
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIaZ3Q9Yt+Pi0SkX7Qc3+w/qotLCxraj72TUjcrO2K/6oAoGCCqGSM49
AwEHoUQDQgAEZAn9MRJqAwmcbIuV2jFKx4q3C1pwrnPoLJPMJt+lv7wPpYvyzUBj
V7WuXWBMk2O7RYLXVCrWUoe8NWsXE+OKOQ==
-----END EC PRIVATE KEY-----

or 

$ openssl ecparam -genkey -name prime256v1 -out key1.pem -noout // -noout을 주면 EC PARAMETERS 삭제됨 
$ cat key1.pem
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFcRnrEHSiO6Xy47Pu8RdAAg4OgwkR67QLPppNO4uKAGoAoGCCqGSM49
AwEHoUQDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupmVx7XQJJvT6hWockHM6kjWGCm
AMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
-----END EC PRIVATE KEY-----

or 

$ openssl ecparam -genkey -name secp256r1 | openssl ec -out key2.pem // ECDSA P-256(secp256r1 Curve) 사용 
using curve name prime256v1 instead of secp256r1   // 대체되며 동일한 기능임  
$ cat key2.pem                 
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFcRnrEHSiO6Xy47Pu8RdAAg4OgwkR67QLPppNO4uKAGoAoGCCqGSM49
AwEHoUQDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupmVx7XQJJvT6hWockHM6kjWGCm
AMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
-----END EC PRIVATE KEY-----

openssl ecparam manual
  https://www.openssl.org/docs/man1.0.2/man1/ecparam.html


EC PRIVATE KEY FORMAT
  https://tools.ietf.org/html/rfc5915
  https://crypto.stackexchange.com/questions/48707/ecdsa-private-key-format


상위에서 다양하게 생성된 Private Key 중 하나를 선택하여 이 기반으로 다양하게 분석.

  • B. 생성된 Private Key 들 중 key.pem 선택 후 분석
$ mv key0.pem key.pem
or
$ mv key1.pem key.pem // 셋 중 아무거나 사용 

  • C.1 key.pem 의 ASN.1 Parser 분석 
BEGIN EC PRIVATE KEY는 Private Key 와 Public Key가 같이 존재하지만, ASN.1으로 OCTET STRINGBIT STRING으로 분할.

// key.pem (BEGIN EC PRIVATE KEY) 
// key.der 일경우 base64 encoding 방식이 아니며 binary이므로 -inform DER 추가   
$ cat key.pem 
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFcRnrEHSiO6Xy47Pu8RdAAg4OgwkR67QLPppNO4uKAGoAoGCCqGSM49
AwEHoUQDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupmVx7XQJJvT6hWockHM6kjWGCm
AMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
-----END EC PRIVATE KEY-----

// ASN.1 으로 Decoding 하면 OCTET STRING의 Hex Dump Private Key정보 존재 와 Public Key 존재 
$ openssl asn1parse -in key.pem  
    0:d=0  hl=2 l= 119 cons: SEQUENCE          
    2:d=1  hl=2 l=   1 prim: INTEGER           :01
    5:d=1  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:57119EB1074A23BA5F2E3B3EEF11740020E0E830911EBB40B3E9A4D3B8B8A006
   39:d=1  hl=2 l=  10 cons: cont [ 0 ]        
   41:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   51:d=1  hl=2 l=  68 cons: cont [ 1 ]        
   53:d=2  hl=2 l=  66 prim: BIT STRING 

// OCTET STRING: Private Key  
// BIT STRING: Public Key 
$ openssl asn1parse -in key.pem -dump  
    0:d=0  hl=2 l= 119 cons: SEQUENCE          
    2:d=1  hl=2 l=   1 prim: INTEGER           :01
    5:d=1  hl=2 l=  32 prim: OCTET STRING      
      0000 - 57 11 9e b1 07 4a 23 ba-5f 2e 3b 3e ef 11 74 00   W....J#._.;>..t.
      0010 - 20 e0 e8 30 91 1e bb 40-b3 e9 a4 d3 b8 b8 a0 06    ..0...@........
   39:d=1  hl=2 l=  10 cons: cont [ 0 ]        
   41:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   51:d=1  hl=2 l=  68 cons: cont [ 1 ]        
   53:d=2  hl=2 l=  66 prim: BIT STRING        
      0000 - 00 04 02 3a 11 92 d3 cf-64 20 44 77 a4 e2 53 f8   ...:....d Dw..S.
      0010 - 36 bb ea a0 92 ea 66 57-1e d7 40 92 6f 4f a8 56   6.....fW..@.oO.V
      0020 - a1 c9 07 33 a9 23 58 60-a6 00 c3 2d 5b f4 d0 ef   ...3.#X`...-[...
      0030 - 39 68 ae e3 9e e7 66 0d-46 0c 5e f2 f3 29 8d 41   9h....f.F.^..).A
      0040 - d4 e0                                             ..



  • C.2 key.pem의 TEXT 기반분석 
Private Key 와 Public Key 분석방법 (명령어 openssl pkey)
// 상위 key.pem 다름 (BEGIN PRIVATE KEY) 이 정보안에 Private Key 정보포함 
// key.der 일경우 base64 encoding 방식이 아니며 binary이므로 -inform DER 추가   
$ openssl pkey -in key.pem -text  
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgVxGesQdKI7pfLjs+
7xF0ACDg6DCRHrtAs+mk07i4oAahRANCAAQCOhGS089kIER3pOJT+Da76qCS6mZX
HtdAkm9PqFahyQczqSNYYKYAwy1b9NDvOWiu457nZg1GDF7y8ymNQdTg
-----END PRIVATE KEY-----
Private-Key: (256 bit)        // 256bit (32byte)
priv:                         // 32bytes 
    57:11:9e:b1:07:4a:23:ba:5f:2e:3b:3e:ef:11:74:
    00:20:e0:e8:30:91:1e:bb:40:b3:e9:a4:d3:b8:b8:
    a0:06
pub:                          // 65byte (1+32bytes+32bytes) Public Key A/B 두개의 키로구성
    04:02:3a:11:92:d3:cf:64:20:44:77:a4:e2:53:f8:
    36:bb:ea:a0:92:ea:66:57:1e:d7:40:92:6f:4f:a8:
    56:a1:c9:07:33:a9:23:58:60:a6:00:c3:2d:5b:f4:
    d0:ef:39:68:ae:e3:9e:e7:66:0d:46:0c:5e:f2:f3:
    29:8d:41:d4:e0
ASN1 OID: prime256v1
NIST CURVE: P-256

$ openssl pkey -in key.pem -noout -text
Private-Key: (256 bit)        // 256bit (32byte)
priv:                         // 32bytes  Private Key 
    57:11:9e:b1:07:4a:23:ba:5f:2e:3b:3e:ef:11:74:
    00:20:e0:e8:30:91:1e:bb:40:b3:e9:a4:d3:b8:b8:
    a0:06
pub:                          // 65byte (1+32bytes+32bytes) Public Key A/B 두개의 키로구성  
    04:02:3a:11:92:d3:cf:64:20:44:77:a4:e2:53:f8:
    36:bb:ea:a0:92:ea:66:57:1e:d7:40:92:6f:4f:a8:
    56:a1:c9:07:33:a9:23:58:60:a6:00:c3:2d:5b:f4:
    d0:ef:39:68:ae:e3:9e:e7:66:0d:46:0c:5e:f2:f3:
    29:8d:41:d4:e0
ASN1 OID: prime256v1
NIST CURVE: P-256




  • BEGIN EC PRIVATE KEY 와 BEGIN PRIVATE KEY 차이 
둘 다 Private Key 와 Public Key를 가지고 있지만 ASN.1의  Data Type 차이일 뿐
  1. BEGIN EC PRIVATE KEY: ASN.1으로 OCTECT STRING 과 BIT STRING으로 분리됨 
  2. BEGIN PRIVATE KEY:  ASN.1의 OCTECT STRING으로 통합되어 쉽게 볼수 있음 

// key.der 일경우 base64 encoding 방식이 아니며 binary이므로 -inform DER 추가   
$ vi test.pem  // Private Key 와 Public Key 같이 가지고 있음 
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgVxGesQdKI7pfLjs+
7xF0ACDg6DCRHrtAs+mk07i4oAahRANCAAQCOhGS089kIER3pOJT+Da76qCS6mZX
HtdAkm9PqFahyQczqSNYYKYAwy1b9NDvOWiu457nZg1GDF7y8ymNQdTg
-----END PRIVATE KEY-----

$ openssl asn1parse -in test.pem // 상위 Private Key 와 Public Key 정보 확인가능 
    0:d=0  hl=3 l= 135 cons: SEQUENCE          
    3:d=1  hl=2 l=   1 prim: INTEGER           :00
    6:d=1  hl=2 l=  19 cons: SEQUENCE          
    8:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   17:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   27:d=1  hl=2 l= 109 prim: OCTET STRING      [HEX DUMP]:306B020101042057119EB1074A23BA5F2E3B3EEF11740020E0E830911EBB40B3E9A4D3B8B8A006A14403420004023A1192D3CF64204477A4E253F836BBEAA092EA66571ED740926F4FA856A1C90733A9235860A600C32D5BF4D0EF3968AEE39EE7660D460C5EF2F3298D41D4E0

$ openssl asn1parse -in test.pem -dump //혹시 몰라서 전체 dump 
    0:d=0  hl=3 l= 135 cons: SEQUENCE          
    3:d=1  hl=2 l=   1 prim: INTEGER           :00
    6:d=1  hl=2 l=  19 cons: SEQUENCE          
    8:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   17:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   27:d=1  hl=2 l= 109 prim: OCTET STRING      
      0000 - 30 6b 02 01 01 04 20 57-11 9e b1 07 4a 23 ba 5f   0k.... W....J#._
      0010 - 2e 3b 3e ef 11 74 00 20-e0 e8 30 91 1e bb 40 b3   .;>..t. ..0...@.
      0020 - e9 a4 d3 b8 b8 a0 06 a1-44 03 42 00 04 02 3a 11   ........D.B...:.
      0030 - 92 d3 cf 64 20 44 77 a4-e2 53 f8 36 bb ea a0 92   ...d Dw..S.6....
      0040 - ea 66 57 1e d7 40 92 6f-4f a8 56 a1 c9 07 33 a9   .fW..@.oO.V...3.
      0050 - 23 58 60 a6 00 c3 2d 5b-f4 d0 ef 39 68 ae e3 9e   #X`...-[...9h...
      0060 - e7 66 0d 46 0c 5e f2 f3-29 8d 41 d4 e0            .f.F.^..).A..


ASN.1 parse 구조 
  1. offset:d  
  2. d: depth
  3. hl: header length (bytes)
  4. l: length (bytes)
  5. cons or prim: tags form

openssl asn1parse
  https://www.openssl.org/docs/manmaster/man1/openssl-asn1parse.html
  https://www.obj-sys.com/docs/acv67/JavaRunTime/com/objsys/asn1j/runtime/Asn1Tag.html

  • C.3 key.pem의 TEXT 기반분석 
Private Key 와 Public Key 분석방법 (명령어 openssl ec)  
바로 이전과 동일하게 나오며, 쉽게 Private Key와 Public Key 좀 더 쉽게 분석가능 
이 Private Key로 2.3 ECDSA 의 Certificate 분석에 사용  

// key.der 일경우 base64 encoding 방식이 아니며 binary이므로 -inform DER 추가   
$ openssl ec -in key.pem -text -noout
read EC key
Private-Key: (256 bit)
priv:
    57:11:9e:b1:07:4a:23:ba:5f:2e:3b:3e:ef:11:74:
    00:20:e0:e8:30:91:1e:bb:40:b3:e9:a4:d3:b8:b8:
    a0:06
pub:   //Prefix(0x04) and Pair of Coordinates (X,Y)   RFC5480 2.2 Subject Public Key 참조 0x04 uncompressed  
    04:02:3a:11:92:d3:cf:64:20:44:77:a4:e2:53:f8:
    36:bb:ea:a0:92:ea:66:57:1e:d7:40:92:6f:4f:a8:
    56:a1:c9:07:33:a9:23:58:60:a6:00:c3:2d:5b:f4:
    d0:ef:39:68:ae:e3:9e:e7:66:0d:46:0c:5e:f2:f3:
    29:8d:41:d4:e0
ASN1 OID: prime256v1
NIST CURVE: P-256

$ openssl ec -in key.pem -text
read EC key
Private-Key: (256 bit)
priv:
    57:11:9e:b1:07:4a:23:ba:5f:2e:3b:3e:ef:11:74:
    00:20:e0:e8:30:91:1e:bb:40:b3:e9:a4:d3:b8:b8:
    a0:06
pub:    //Prefix(0x04) and Pair of Coordinates (X,Y)   RFC5480 2.2 Subject Public Key 참조 0x04 uncompressed  
    04:02:3a:11:92:d3:cf:64:20:44:77:a4:e2:53:f8:
    36:bb:ea:a0:92:ea:66:57:1e:d7:40:92:6f:4f:a8:
    56:a1:c9:07:33:a9:23:58:60:a6:00:c3:2d:5b:f4:
    d0:ef:39:68:ae:e3:9e:e7:66:0d:46:0c:5e:f2:f3:
    29:8d:41:d4:e0
ASN1 OID: prime256v1
NIST CURVE: P-256
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFcRnrEHSiO6Xy47Pu8RdAAg4OgwkR67QLPppNO4uKAGoAoGCCqGSM49
AwEHoUQDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupmVx7XQJJvT6hWockHM6kjWGCm
AMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
-----END EC PRIVATE KEY-----

$ openssl ec -in key.pem -text -pubout  // 실제 Public Key 추출 가능(이는 아래의 Certificate 사용) 
read EC key
Private-Key: (256 bit)
priv:
    57:11:9e:b1:07:4a:23:ba:5f:2e:3b:3e:ef:11:74:
    00:20:e0:e8:30:91:1e:bb:40:b3:e9:a4:d3:b8:b8:
    a0:06
pub:   //Prefix(0x04) and Pair of Coordinates (X,Y)   RFC5480 2.2 Subject Public Key 참조 0x04 uncompressed  
    04:02:3a:11:92:d3:cf:64:20:44:77:a4:e2:53:f8:
    36:bb:ea:a0:92:ea:66:57:1e:d7:40:92:6f:4f:a8:
    56:a1:c9:07:33:a9:23:58:60:a6:00:c3:2d:5b:f4:
    d0:ef:39:68:ae:e3:9e:e7:66:0d:46:0c:5e:f2:f3:
    29:8d:41:d4:e0
ASN1 OID: prime256v1
NIST CURVE: P-256
writing EC key
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupm
Vx7XQJJvT6hWockHM6kjWGCmAMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
-----END PUBLIC KEY-----

openssl ec manual
  https://www.openssl.org/docs/man1.0.2/man1/ec.html
openssl ec command 예제
  https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations
openssl command 예제
  https://wiki.openssl.org/index.php/Command_Line_Utilities

  https://en.wikipedia.org/wiki/X.690


  • Base64 Code To Hex로 Private Key 재검증 
ASN.1 이 필요하지만, Base64로 직접 Hex로 변경하여  ASN.1 OCTECT STRING으로 통합된 곳 확인가능

// key.pem (BEGIN EC PRIVATE KEY) 
MHcCAQEEIFcRnrEHSiO6Xy47Pu8RdAAg4OgwkR67QLPppNO4uKAGoAoGCCqGSM49AwEHoUQDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupmVx7XQJJvT6hWockHM6kjWGCmAMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
//base64 to Hex
30770201010420178b69b8b92c8f17366eb7ac816bf04c7410b022c01942a10acc4f791c4a7f9ba00a06082a8648ce3d030107a14403420004353693ac07ddd2e5f1231ef3e86f97fcfd2365653f9bc2c261513e36cdd4b3df1d4b800a5f25a4bc96fa0230c0f4a338837da9c30450cbb8e43ce07a6aede8d0

// key.pem (BEGIN PRIVATE KEY) 
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgVxGesQdKI7pfLjs+7xF0ACDg6DCRHrtAs+mk07i4oAahRANCAAQCOhGS089kIER3pOJT+Da76qCS6mZXHtdAkm9PqFahyQczqSNYYKYAwy1b9NDvOWiu457nZg1GDF7y8ymNQdTg
//base64 to Hex
308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b020101042057119eb1074a23ba5f2e3b3eef11740020e0e830911ebb40b3e9a4d3b8b8a006a14403420004023a1192d3cf64204477a4e253f836bbeaa092ea66571ed740926f4fa856a1c90733a9235860a600c32d5bf4d0ef3968aee39ee7660d460c5ef2f3298d41d4e0

Base64 Encode/Decode Tool 이 없다면 아래의 사이트에서 변경 

Base64 Encode/Decode Website
  https://base64.guru/converter/encode/hex
  https://base64.guru/converter/decode/hex


2.2 ECDSA 의 Certificate Signature 분석 

이 부분은 CA가 Certificate 의 Signature 부분을 생성부분을 이해하기 위해서 간단하게 구성한 것이므로, 알면 넘어가자
이부분은 ECDSA Certificate의 Signature Sign/Verify 부분을 이해하는 것으로, 나중에 구조그림을 보면 쉽게 이해간다. 


Signature는 Private Key 기반으로 만들고, Public Key로 검증이 가능하니 아래와 같이 각 Key들을 확인 

  • Private Key 동일하게 생성
// Create Private key and Public Key (상위와 key.pem 동일)
$ openssl ecparam -genkey -name prime256v1 -noout -out private.pem //새로 생성하고 할 경우, 나는 상위 key.pem 복사

$ cat private.pem  //기존의 key.pem 과 동일 
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFcRnrEHSiO6Xy47Pu8RdAAg4OgwkR67QLPppNO4uKAGoAoGCCqGSM49
AwEHoUQDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupmVx7XQJJvT6hWockHM6kjWGCm
AMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
-----END EC PRIVATE KEY-----

$ openssl ec -in private.pem -text -pubout   //상위 key.pem 과 동일하며, Sign/Verify 테스트  
read EC key
Private-Key: (256 bit)
priv:
    57:11:9e:b1:07:4a:23:ba:5f:2e:3b:3e:ef:11:74:      //ECC Private Key 256bit (32bytes)
    00:20:e0:e8:30:91:1e:bb:40:b3:e9:a4:d3:b8:b8:
    a0:06
pub:      //Prefix(0x04) and Pair of Coordinates (X,Y)   RFC5480 2.2 Subject Public Key 참조 0x04 uncompressed  
    04:02:3a:11:92:d3:cf:64:20:44:77:a4:e2:53:f8:        //ECC Public Key X (32bytes)
    36:bb:ea:a0:92:ea:66:57:1e:d7:40:92:6f:4f:a8:
    56:a1:c9:07:33:a9:23:58:60:a6:00:c3:2d:5b:f4:        //ECC Public Key Y (32bytes)
    d0:ef:39:68:ae:e3:9e:e7:66:0d:46:0c:5e:f2:f3:
    29:8d:41:d4:e0
ASN1 OID: prime256v1
NIST CURVE: P-256
writing EC key
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupm
Vx7XQJJvT6hWockHM6kjWGCmAMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
-----END PUBLIC KEY-----

  • Private Key에서 Public Key만 추출
// Save public key (Public Key 추출)
$ openssl ec -in private.pem -pubout -out public.pem   //상위 private.pem 에서 public key만 추출

$ cat public.pem  
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupm
Vx7XQJJvT6hWockHM6kjWGCmAMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
-----END PUBLIC KEY-----

$ openssl asn1parse -in public.pem -dump //ECC Public key 확인완료 prefix: 0x04 coordinates (x,y) 
    0:d=0  hl=2 l=  89 cons: SEQUENCE
    2:d=1  hl=2 l=  19 cons: SEQUENCE
    4:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   13:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   23:d=1  hl=2 l=  66 prim: BIT STRING
      0000 - 00 04 02 3a 11 92 d3 cf-64 20 44 77 a4 e2 53 f8   ...:....d Dw..S.       //Public Key X (32bytes)
      0010 - 36 bb ea a0 92 ea 66 57-1e d7 40 92 6f 4f a8 56   6.....fW..@.oO.V
      0020 - a1 c9 07 33 a9 23 58 60-a6 00 c3 2d 5b f4 d0 ef   ...3.#X`...-[...       //Public Key Y (32bytes) 
      0030 - 39 68 ae e3 9e e7 66 0d-46 0c 5e f2 f3 29 8d 41   9h....f.F.^..).A
      0040 - d4 e0


  • Hash를 이용하여 Signature 생성(Private Key) 및 검증(Public Key)방법 
Signature 의 역할은 아래와 간단히 Public Key로 검증하기 위해서 필요하다.
이 부분은 아래의 CA의 구조 및 역할을 보면 다시 이해 가능

준비사항
  1. private.pem 
  2. public.pem
  3. yourinputdocument : Test File 

SHA-256 Hash 
  https://ko.wikipedia.org/wiki/SHA



Sample Data 생성하여 TEST하며, Certificate의 Signature의 원리파악을 해보자

1. TEST DATA or TEXT 생성 

Sample Data 생성하여 TEST하며, Certificate의 Signature일 경우 Certificate 정보
$ vi yourinputdocument      // 1. TEST DATA 생성
Hellow World !!!!
or 
$ cat >  yourinputdocument
Hellow World !!!!

    2. Private Key 기반으로 Signature 생성 
    1. TEST DATA를 SHA256로 Hash를 이용
    2. 상위에서 생성된 Hash를  Private Key 기반으로 Sign을 하여 Signature를 생성
    Sign something: ECDSA의 Private Key를 이용하여 Sign 를 진행하여 yourinput.sha256 Signature 생성
    $ openssl dgst -sha256 -sign private.pem -out yourinput.sha256 yourinputdocument  // SHA256기반으로 Sign 
    

    3. 생성된 Signature(yourinput.sha256) 확인

    생성된 Signature File의 크기 및 구조파악하며 256(32byte) 가 아니며, 72bytes (Certificate의 Signature 와 동일)
    $ hd yourinput.sha256  // 상위에서 생성된 결과 (Signature) 를 확인 (TEST DATA의 크기를 늘려도 크기는 동일) 
    or
    $ xxd yourinput.sha256
    or
    $ hexdump yourinput.sha256  //아래의 값은 상위 2.Signature를 생성될때마다 매번 값이 변경됨 
    0000000 4430 2002 0c3b 1c15 537f 1297 6ac7 575c
    0000010 a62a d386 0a3d 3973 aa69 a750 5ffd 1198
    0000020 b1dd 30b2 2002 5e55 236b 1188 eea8 6719
    0000030 b507 37d2 272e d84a ced1 91fc 59cb 6e9b
    0000040 2adc a97d b373
    0000046
    


    4. Signature를 Public Key로 검증(Verification) 

    To verify: Public Key를 이용하여 yourinput.sha256 Signature로 이를 검증
    $ openssl dgst -sha256 -verify public.pem -signature yourinput.sha256 yourinputdocument
    Verified OK


    OpenSSL dgst
      https://www.openssl.org/docs/man1.1.0/man1/openssl-dgst.html

    Digital Signature Algorithm 
     Public Key 와 Private Key 기반으로 상위와 같이 구성
      https://en.wikipedia.org/wiki/Digital_Signature_Algorithm
      https://cryptobook.nakov.com/digital-signatures

    • Web Site에서 직접 확인방법
    상위내용을 쉽게 Web에서  Sign/Verification 을 쉽게 확인가능 
    1. EC Private Key 와 EC Public Key Hex 생성 
    2. Data에서 Signature Algorithm (SHA256 with ECDSA) 를 이용하여 Signature Value생성
    3. Signature Value(Hash Checksum)기반으로 Data 검증완료  
      https://kjur.github.io/jsrsasign/sample/sample-ecdsa.html

    • ECDSA 의 Signature 관련부분 (Data 검증부분) 
    openssl dgst 을 이용하여 Signature 기능검증
      https://superuser.com/questions/737574/openssl-ecdsa-sign-and-verify-file
      https://medium.com/@skloesch/openssl-and-ecdsa-signatures-db60c005b1f4
      https://superuser.com/questions/1258478/how-to-get-ecsda-with-p-256-and-sha256-in-openssl



    2.3 ECDSA 기반의 Certificate 분석 

    이미 위에서 ECDSA의 Private Key/Public Key 기반으로 Certificate 생성했지만, 이를 분석하기 위해서 아래와 같이 다시 생성 후 이를 분석

    • ECDSA 기반의 Certificate 생성 
    // 상위에서 생긴 key.pem 기반으로 X.509로 Certificate 생성 
    $ openssl req -new -key key.pem -x509 -nodes -days 365 -out cert.pem 
    

    openssl req manual
    https://www.openssl.org/docs/man1.0.2/man1/openssl-req.html

    • ECDSA 기반의 Certificate 분석 
    상위에서 생성된 TEST Certificate를 전체세부분석해보도록 하자. 
    Private Key는 이곳에 저장하지 못하며, Public Key를 이곳에 저장한다.
    $ openssl x509 -in cert.pem -noout -text  // 상위 Certifacte 전체 분석 
    Certificate:
        Data:
            Version: 3 (0x2)    // 인증서 Version
            Serial Number:    // 인증서 Serial Number로 Unique하며, 매번 CA 생성시마다 다르며, 최대 20bytes 
                14:ad:af:2e:18:63:68:60:8e:36:be:05:99:66:b2:e6:da:b7:0d:8c
            Signature Algorithm: ecdsa-with-SHA256                      // 인증서 Signature Alogirthm ECDSA 와 SHA256 (아래 값이 나옴) 
            Issuer: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
            Validity                                  // 인증서 유효기간 (1년) 
                Not Before: Jul  6 13:34:08 2020 GMT
                Not After : Jul  6 13:34:08 2021 GMT
            Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
            Subject Public Key Info:
                Public Key Algorithm: id-ecPublicKey
                    Public-Key: (256 bit)        //256bit (32bytes)  상위 key.pem 부분과 동일(상위 key.pem 의 Public Key 만 사용) 
                    pub:
                        04:02:3a:11:92:d3:cf:64:20:44:77:a4:e2:53:f8:   //Public Key X (32bytes) 상위와 동일
                        36:bb:ea:a0:92:ea:66:57:1e:d7:40:92:6f:4f:a8:
                        56:a1:c9:07:33:a9:23:58:60:a6:00:c3:2d:5b:f4:
                        d0:ef:39:68:ae:e3:9e:e7:66:0d:46:0c:5e:f2:f3:  //Public Key Y (32bytes) 상위와 동일 
                        29:8d:41:d4:e0
                    ASN1 OID: prime256v1
                    NIST CURVE: P-256
            X509v3 extensions:
                X509v3 Subject Key Identifier:  // 상위 Pubic Key의 SHA1 값 (아래에서 확인)   
                    1A:2B:F7:8D:87:A4:E7:35:2E:05:92:C8:60:69:F8:C7:7E:F5:46:FB
                X509v3 Authority Key Identifier: // Subject Key Identifier 와 Authority Key Identifier 동일값 
                    keyid:1A:2B:F7:8D:87:A4:E7:35:2E:05:92:C8:60:69:F8:C7:7E:F5:46:FB
    
                X509v3 Basic Constraints: critical  // CA True 이면, Digital Signature 가 아님, 이부분 아래다시 설명 
                    CA:TRUE
        Signature Algorithm: ecdsa-with-SHA256    //72byte , Signature로   생성될때마다 다르며, Public Key로 검증 
             30:46:02:21:00:fd:39:0d:c0:cf:72:8c:9d:81:c3:0c:65:0d:
             21:50:ac:54:9b:e1:ca:2f:f8:f3:e6:5d:62:36:41:ae:79:57:
             20:02:21:00:fc:ef:4e:4a:14:30:0c:5c:a6:96:bb:1c:23:8c:
             1c:ba:f0:1b:fa:04:32:ad:c9:3c:45:d3:bc:f6:14:01:be:e5
    


    Subject Key Identifier(SHA1)
    //Public Key
    04023a1192d3cf64204477a4e253f836bbeaa092ea66571ed740926f4fa856a1c90733a9235860a600c32d5bf4d0ef3968aee39ee7660d460c5ef2f3298d41d4e0
    //Subject Key Identifier
    1a2bf78d87a4e7352e0592c86069f8c77ef546fb
    SHA1 ,Input Type: TEXT->HEX사용


    • ECDSA X.509 세부분석 

    $ openssl x509 -in cert.pem -noout -dates  // 날짜 분석 
    notBefore=Jul  6 13:34:08 2020 GMT
    notAfter=Jul  6 13:34:08 2021 GMT
    
    $ openssl x509 -in cert.pem -noout -pubkey  // 상위 PublicKey Base64 Encode
    -----BEGIN PUBLIC KEY-----
    MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAjoRktPPZCBEd6TiU/g2u+qgkupm
    Vx7XQJJvT6hWockHM6kjWGCmAMMtW/TQ7zloruOe52YNRgxe8vMpjUHU4A==
    -----END PUBLIC KEY-----
    
    $ openssl asn1parse -in cert.pem   //ASN.1 Decode 
        0:d=0  hl=4 l= 480 cons: SEQUENCE          
        4:d=1  hl=4 l= 389 cons: SEQUENCE          
        8:d=2  hl=2 l=   3 cons: cont [ 0 ]        
       10:d=3  hl=2 l=   1 prim: INTEGER           :02
       13:d=2  hl=2 l=  20 prim: INTEGER           :14ADAF2E186368608E36BE059966B2E6DAB70D8C
       35:d=2  hl=2 l=  10 cons: SEQUENCE          
       37:d=3  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
       47:d=2  hl=2 l=  69 cons: SEQUENCE          
       49:d=3  hl=2 l=  11 cons: SET               
       51:d=4  hl=2 l=   9 cons: SEQUENCE          
       53:d=5  hl=2 l=   3 prim: OBJECT            :countryName
       58:d=5  hl=2 l=   2 prim: PRINTABLESTRING   :AU
       62:d=3  hl=2 l=  19 cons: SET               
       64:d=4  hl=2 l=  17 cons: SEQUENCE          
       66:d=5  hl=2 l=   3 prim: OBJECT            :stateOrProvinceName
       71:d=5  hl=2 l=  10 prim: UTF8STRING        :Some-State
       83:d=3  hl=2 l=  33 cons: SET               
       85:d=4  hl=2 l=  31 cons: SEQUENCE          
       87:d=5  hl=2 l=   3 prim: OBJECT            :organizationName
       92:d=5  hl=2 l=  24 prim: UTF8STRING        :Internet Widgits Pty Ltd
      118:d=2  hl=2 l=  30 cons: SEQUENCE          
      120:d=3  hl=2 l=  13 prim: UTCTIME           :200706133408Z
      135:d=3  hl=2 l=  13 prim: UTCTIME           :210706133408Z
      150:d=2  hl=2 l=  69 cons: SEQUENCE          
      152:d=3  hl=2 l=  11 cons: SET               
      154:d=4  hl=2 l=   9 cons: SEQUENCE          
      156:d=5  hl=2 l=   3 prim: OBJECT            :countryName
      161:d=5  hl=2 l=   2 prim: PRINTABLESTRING   :AU
      165:d=3  hl=2 l=  19 cons: SET               
      167:d=4  hl=2 l=  17 cons: SEQUENCE          
      169:d=5  hl=2 l=   3 prim: OBJECT            :stateOrProvinceName
      174:d=5  hl=2 l=  10 prim: UTF8STRING        :Some-State
      186:d=3  hl=2 l=  33 cons: SET               
      188:d=4  hl=2 l=  31 cons: SEQUENCE          
      190:d=5  hl=2 l=   3 prim: OBJECT            :organizationName
      195:d=5  hl=2 l=  24 prim: UTF8STRING        :Internet Widgits Pty Ltd
      221:d=2  hl=2 l=  89 cons: SEQUENCE          
      223:d=3  hl=2 l=  19 cons: SEQUENCE          
      225:d=4  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
      234:d=4  hl=2 l=   8 prim: OBJECT            :prime256v1
      244:d=3  hl=2 l=  66 prim: BIT STRING        
      312:d=2  hl=2 l=  83 cons: cont [ 3 ]        
      314:d=3  hl=2 l=  81 cons: SEQUENCE          
      316:d=4  hl=2 l=  29 cons: SEQUENCE          
      318:d=5  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Identifier
      323:d=5  hl=2 l=  22 prim: OCTET STRING      [HEX DUMP]:04141A2BF78D87A4E7352E0592C86069F8C77EF546FB
      347:d=4  hl=2 l=  31 cons: SEQUENCE          
      349:d=5  hl=2 l=   3 prim: OBJECT            :X509v3 Authority Key Identifier
      354:d=5  hl=2 l=  24 prim: OCTET STRING      [HEX DUMP]:301680141A2BF78D87A4E7352E0592C86069F8C77EF546FB
      380:d=4  hl=2 l=  15 cons: SEQUENCE          
      382:d=5  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
      387:d=5  hl=2 l=   1 prim: BOOLEAN           :255
      390:d=5  hl=2 l=   5 prim: OCTET STRING      [HEX DUMP]:30030101FF
      397:d=1  hl=2 l=  10 cons: SEQUENCE          
      399:d=2  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
      409:d=1  hl=2 l=  73 prim: BIT STRING  
    


    OpenSSL 로 x509로 분석시 옵션
      https://www.openssl.org/docs/man1.0.2/man1/openssl-x509.html

    openssl asn1parse
      https://www.openssl.org/docs/manmaster/man1/openssl-asn1parse.html


    3. Certificate Authority 기본동작 


    • Certificate Authority 역할 및 동작 
    Certificate Authority 의 역할은 digital certificate을 발행하는 것이며, CA는 제 3자의 역할로 발행이 되어 인증이 되는 시스템으로 보인다.

    아래 그림처럼 CA는 Certificate를 검증하고, CA의 Private Key로 Encryption 하여 나오는 Digital Signature를 Digital Certificate에 추가하여 발행


    1. 좌측: CA의 의해 Digital Certificate 발행 전  
    2. 우측: CA의 의해 Digital Certificate 발행 후  

    세부내용은 아래 wiki 참조 

    CA(Cerficate Authority)
      https://en.wikipedia.org/wiki/Certificate_authority

    Digital certificate 
       https://en.wikipedia.org/wiki/Public_key_certificate

    • RootCA / SubCA / Digital Signature Sign
    1. Layer 1:  Root CA로 Self로 Private Key로 Signature 생성  
    2. Layer 2:  Intermediate Certificate로 Layer 1의 Private Key로 Signature 생성  
    3. Layer 3:  End 유저가 사용 Layer 2에 Private Key로 Signature 생성  

    아래의 경우 3단계로 구성이 되어있지만, 글을 읽다보면, 다른 구성도 가능하며, 단계 역시  사용자가 사용하기 나름인 것 같다.
    하지만 기본구조를 보면 다음과 같기에 이를 알아두도록하자

    Signature 의 경우 CA의 Private Key를 이용하며, 이는 CA가 검증을 할 수 있도록 하는 기능을 하는 구조이며, 이 부분은 상위 Signature 사용방법을 보자


    1. Certificate 의 Issuer:  인증서 발급자 (Reference)
    2. Certificate 의 Subject: 현재 Certificate 소유자 
    3. Public Key의 역할은 Sign이 아니라 Verify용으로 검증 

    상위 Signature를 이해하면 아래 Sign/Verify를 쉽게 이해 
    https://en.wikipedia.org/wiki/Root_certificate

    세부내용은 아래링크 참조
      https://en.wikipedia.org/wiki/Root_certificate
      https://en.wikipedia.org/wiki/Certificate_authority
      https://en.wikipedia.org/wiki/Public_key_certificate


    3.1 ECDSA 기반의 CA 와 Certificate 생성 

    상위구조를 이해를 했으면, 나의 경우는 3단계의 구성이 아니라 간단하게 Root CA 와 End Certificate로 두 단계 구성으로 만들어 보자. 
    Root CA는 CA로 End Certificate는 Server로 아래와 같이 생성해보자 

    • ECDSA Private Key 생성 후 CA 생성준비 완료 
    상위 처럼 Private Key 다시 생성

    //GENERATING CERTIFICATE Authority 
    $ openssl ecparam -genkey -name prime256v1 -out ca.key
    $ cat ca.key
    -----BEGIN EC PARAMETERS-----
    BggqhkjOPQMBBw==
    -----END EC PARAMETERS-----
    -----BEGIN EC PRIVATE KEY-----
    MHcCAQEEIF54a1vqeHiIR3aMKOkBEgVMk/7w12OnO3s89Dq5rO6KoAoGCCqGSM49
    AwEHoUQDQgAEXbLvFW468tBNs6r6j8yInfZoTeCTKfdkRIS75r3lin6FGGfGhLml
    Z1oO5+nFqcmbEIHBTs5l327iCMuYPq8H8w==
    -----END EC PRIVATE KEY-----
    

    • CA(Certificate Authority) 생성완료 
    상위에서 만든 Private Key 기반으로 Certificate Authrity (Root CA) 생성, 10년 짜리로 CA를 X.509로 바로 생성을 한다 

    /*
    *Cerificate Authorities
      Country Name(C): KR
      State or Province Name(ST):SL
      Locality Name(L): Seoul
      Organization Name(O):Jeonghun  
      Organizational Unit Name(OU):JHLEE
      Common Name(CN):JeonghunCA
      Email Address:
    
    -subj "/C=KR/ST=SL/L=Seoul/O=Jeonghun/OU=JHLEE/CN=JeonghunCA"
    */
    
    $ openssl req -x509 -new -SHA256 -nodes -key ca.key -days 3650 -out ca.crt -subj "/C=KR/ST=SL/L=Seoul/O=Jeonghun/OU=JHLEE/CN=JeonghunCA"  
    $ cat ca.crt        //상위 생성시마다 값이 다르므로 동일값이 나올수 없다
    -----BEGIN CERTIFICATE-----
    MIICGTCCAb+gAwIBAgIUK+hYEK24Ewtrib+XxYcws14T+4gwCgYIKoZIzj0EAwIw
    YjELMAkGA1UEBhMCS1IxCzAJBgNVBAgMAlNMMQ4wDAYDVQQHDAVTZW91bDERMA8G
    A1UECgwISmVvbmdodW4xDjAMBgNVBAsMBUpITEVFMRMwEQYDVQQDDApKZW9uZ2h1
    bkNBMB4XDTIwMDcwNzA1NTI1MloXDTMwMDcwNTA1NTI1MlowYjELMAkGA1UEBhMC
    S1IxCzAJBgNVBAgMAlNMMQ4wDAYDVQQHDAVTZW91bDERMA8GA1UECgwISmVvbmdo
    dW4xDjAMBgNVBAsMBUpITEVFMRMwEQYDVQQDDApKZW9uZ2h1bkNBMFkwEwYHKoZI
    zj0CAQYIKoZIzj0DAQcDQgAEXbLvFW468tBNs6r6j8yInfZoTeCTKfdkRIS75r3l
    in6FGGfGhLmlZ1oO5+nFqcmbEIHBTs5l327iCMuYPq8H86NTMFEwHQYDVR0OBBYE
    FPHSACWs/mXd/PG3IYPEkKn7NTKrMB8GA1UdIwQYMBaAFPHSACWs/mXd/PG3IYPE
    kKn7NTKrMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgRJsRlghF
    X7qOod/JlqoKiHuQY0jMuldlbz7W/jGEXPQCIQDxoj/CXkDllYDLy1OM7jLSyTOF
    hKdgqMjWIUWw2Ui3Mg==
    -----END CERTIFICATE-----
    



    • Server CSR 생성완료
    ECDSA로 Private Key 기반으로 Server Certificate Signing Request로 상위와 비슷하게 생성을 해보자.
    CSR(Certificate Signing Request)는 아직 X.509로 Certificate가 아니며 Request 상태
    현재 상위 CA와 Server CSR 는 Reference 상태가 아님

    //CREATING A ECDSA CSR(certificate signing request)
    $ openssl ecparam -genkey -name prime256v1 -out server.key
    $ cat server.key
    -----BEGIN EC PARAMETERS-----
    BggqhkjOPQMBBw==
    -----END EC PARAMETERS-----
    -----BEGIN EC PRIVATE KEY-----
    MHcCAQEEIC6SklucSfbgPAn+UI6u2bIHdotXOofYam/nqM18R2l6oAoGCCqGSM49
    AwEHoUQDQgAEWnx+hVyhasx53hxJ5cWbdde08ZCPvbvdGjIX/RWif1S9ZZ2ZtUGU
    B592OyuheBVQS6rQZdIgQVIE/QmORQDDOA==
    -----END EC PRIVATE KEY-----
    
    // -subj "/C=KR/ST=SL/L=Seoul/O=Jeonghun/OU=JHLEE/CN=ServerCert" 
    $ openssl req -new -SHA256 -key server.key -nodes -out server.csr -subj "/C=KR/ST=SL/L=Seoul/O=Jeonghun/OU=JHLEE/CN=ServerCert"
    $ cat server.csr
    -----BEGIN CERTIFICATE REQUEST-----
    MIIBHjCBxAIBADBiMQswCQYDVQQGEwJLUjELMAkGA1UECAwCU0wxDjAMBgNVBAcM
    BVNlb3VsMREwDwYDVQQKDAhKZW9uZ2h1bjEOMAwGA1UECwwFSkhMRUUxEzARBgNV
    BAMMClNlcnZlckNlcnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARafH6FXKFq
    zHneHEnlxZt117TxkI+9u90aMhf9FaJ/VL1lnZm1QZQHn3Y7K6F4FVBLqtBl0iBB
    UgT9CY5FAMM4oAAwCgYIKoZIzj0EAwIDSQAwRgIhANK/U6C2NNPFvTTnBqb83wX0
    b8xMxIYqrcyS9Qq6tCzAAiEAtVGTBPKLMtu2zYNqd/lO6n1AJq+6tZFkt7RR42L8
    oVY=
    -----END CERTIFICATE REQUEST-----
    

    • Server CSR(Certificate Sigining Request) 분석 

    /* 생성된 CSR 분석 , Certificate가 아님 
    - 아직 X.509 Format 이 아님 
    - 아직 Serial Number 와 Validity 가 없음 
    */ 
    $ openssl req -in server.csr -noout -text 
    Certificate Request:
        Data:
            Version: 1 (0x0)
            Subject: C = KR, ST = SL, L = Seoul, O = Jeonghun, OU = JHLEE, CN = ServerCert
            Subject Public Key Info:
                Public Key Algorithm: id-ecPublicKey
                    Public-Key: (256 bit)
                    pub:
                        04:5a:7c:7e:85:5c:a1:6a:cc:79:de:1c:49:e5:c5:
                        9b:75:d7:b4:f1:90:8f:bd:bb:dd:1a:32:17:fd:15:
                        a2:7f:54:bd:65:9d:99:b5:41:94:07:9f:76:3b:2b:
                        a1:78:15:50:4b:aa:d0:65:d2:20:41:52:04:fd:09:
                        8e:45:00:c3:38
                    ASN1 OID: prime256v1
                    NIST CURVE: P-256
            Attributes:
                a0:00
        Signature Algorithm: ecdsa-with-SHA256            /* Server Certificate 생성때 다시 변경됨 */ 
             30:46:02:21:00:d2:bf:53:a0:b6:34:d3:c5:bd:34:e7:06:a6:
             fc:df:05:f4:6f:cc:4c:c4:86:2a:ad:cc:92:f5:0a:ba:b4:2c:
             c0:02:21:00:b5:51:93:04:f2:8b:32:db:b6:cd:83:6a:77:f9:
             4e:ea:7d:40:26:af:ba:b5:91:64:b7:b4:51:e3:62:fc:a1:56
    
    

    openssl req manual
       https://www.openssl.org/docs/man1.0.2/man1/openssl-req.html

    • Server CSR의 확장정보변경준비  
    $ vi v3.ext   // CSR의 추가 확장정보 (CA: FALSE 와 digitalSignature)  
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = ahyuo79.blogspot.com
    

    X.509 확장정보는 아래 참조
      https://en.wikipedia.org/wiki/X.509#Extensions_informing_a_specific_usage_of_a_certificate
      https://en.wikipedia.org/wiki/X.509


    • Server Certificate 최종생성
    상위 CA 기반으로  Server CSR를 이용하여 Server Certificate (X.509) 생성완료 (CA Reference)


     // CA기반으로 server.crt 발행(issue) 
    /* 
      -CA filename    : CA filename  
      -CAkey filename : CA private key를 Sign을 하기 위해서 사용
      -CAcreateserial : CA serial file이 존재하지 않는다면 자동생성한 후 CA 02로 되고, CA에 의해 발행된 Certificate는 1을 가짐
    
    --------  기타 옵션 세부사항은 아래링크 참조
      or 
      -CAserial filename : 본인이 직접 넣어 사용 
      -set_serial n : -CA와 함께사용하며, 직접 n번째 Sign
      -CAform DER|PEM|P12 : 현재 PEM으로 default  
    */
     
    $ openssl x509 -req -SHA256 -extfile v3.ext -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
    



    3.2 ECDSA 기반의 CA 와 Certificate 분석

    상위 3.1에서 생성된 CA와 Server Certificate 세부적으로 분석해보자 

    반드시 상위 3.1에서 CA 와 Server Certificate 생성 후 분석 진행 

    • Server Certificate 세부분석 전 알아야 할 사항  
    두 인증서를 분석을 해보면, Signature의 경우 Public Key로 구성하며, Issuer의 CN을 보면 Reference를 알 수 있으므로, 이름 및 다른 값을 반드시 정해야겠음

    1. Authority Key Identifier: JeonghunCA의 Public Key Hash Value이며 CA의 Subject Key Id와 동일 
    2. Subject Key Identifier:  CA와 다르게 존재하지 않음 
    3. Basic Constraints: CA 인지 아닌지 구분
    4. Key Usage: 주 목적은 Certificate의 Public Key의 사용용도의 허용기능
      1. Digital Signature: Digital Signature를 검증하기 위해서 사용이라는데, 이해가 안감
      2. Non Repudiation: 추후 이해하도록함
      3. Key Encipherment
      4. Data Encipherment

    - RFC5280의 세부내용 

    Key Usage (아래 X.509 분석부분과 같이 확인)

      https://tools.ietf.org/html/rfc5280#section-4.2.1.3
     
    Subject Alternative Name (아래 X.509 분석부분과 같이 확인)
      https://tools.ietf.org/html/rfc5280#section-4.2.1.6


    • Server Certificate 세부분석 
    아래의 CA 세부분석과 같이 비교해보면 분석을 해야하며, Certificate 의 Public Key 부분은 상위에 너무 많이 설명해서 생략 
    $ openssl pkey -in server.key -noout -text  // server.key 분석 
    Private-Key: (256 bit)
    priv:
        2e:92:92:5b:9c:49:f6:e0:3c:09:fe:50:8e:ae:d9:
        b2:07:76:8b:57:3a:87:d8:6a:6f:e7:a8:cd:7c:47:
        69:7a
    pub:
        04:5a:7c:7e:85:5c:a1:6a:cc:79:de:1c:49:e5:c5:
        9b:75:d7:b4:f1:90:8f:bd:bb:dd:1a:32:17:fd:15:
        a2:7f:54:bd:65:9d:99:b5:41:94:07:9f:76:3b:2b:
        a1:78:15:50:4b:aa:d0:65:d2:20:41:52:04:fd:09:
        8e:45:00:c3:38
    ASN1 OID: prime256v1
    NIST CURVE: P-256
    
    /* 
    CA가 완전 동일하더라도, 
    매번 Server Certificate가 생성될 때마다 Validity 가 변경 될 것이며, 
    Serial Number도 Unique 하도록 설정되어 다르므로, 
    Signature Algorithm 의 (signatureValue)값 역시 Server Certificate 생성될때마다 자동 변경된다. 
    */
    
    $ openssl x509 -in server.crt -noout -text  // server.crt 분석 
    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number: // Unique 해야하며 CA에 의해 할당되어진 값
                46:5d:19:4d:d3:40:43:9b:0b:2a:91:2e:55:f8:64:fe:d6:8f:9f:f3
            Signature Algorithm: ecdsa-with-SHA256
            Issuer: C = KR, ST = SL, L = Seoul, O = Jeonghun, OU = JHLEE, CN = JeonghunCA // 인증서 발급자 (Reference), 즉 CA 
            Validity  // 인증서 유효기간 (1년) 
                Not Before: Jul  7 06:01:52 2020 GMT
                Not After : Jul  7 06:01:52 2021 GMT
            Subject: C = KR, ST = SL, L = Seoul, O = Jeonghun, OU = JHLEE, CN = ServerCert // 인증서 소유자 
            Subject Public Key Info:         // 인증서 Public Key 정보 (server.key)
                Public Key Algorithm: id-ecPublicKey
                    Public-Key: (256 bit)
                    pub:
                        04:5a:7c:7e:85:5c:a1:6a:cc:79:de:1c:49:e5:c5:
                        9b:75:d7:b4:f1:90:8f:bd:bb:dd:1a:32:17:fd:15:
                        a2:7f:54:bd:65:9d:99:b5:41:94:07:9f:76:3b:2b:
                        a1:78:15:50:4b:aa:d0:65:d2:20:41:52:04:fd:09:
                        8e:45:00:c3:38
                    ASN1 OID: prime256v1
                    NIST CURVE: P-256
            X509v3 extensions:  // 상위 v3.ext 확인 
                X509v3 Authority Key Identifier:    //CA의 Subject Key Id 동일하며, Server의 Subject Key Id는 없음  
                    keyid:F1:D2:00:25:AC:FE:65:DD:FC:F1:B7:21:83:C4:90:A9:FB:35:32:AB
    
                X509v3 Basic Constraints:      // CA:FALSE 로 CA가 아니며 Digital Signature 용 사용
                    CA:FALSE
                X509v3 Key Usage:          //Digital Signature용 
                    Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
                X509v3 Subject Alternative Name:  //Digital Signature용 DNS에 website 주소 입력
                    DNS:ahyuo79.blogspot.com
        Signature Algorithm: ecdsa-with-SHA256  // Certificate를 생성마다 값이 변경되며, 이값을 변경주는 요소 (Validity와 Serial Number 예상)
             30:45:02:21:00:e9:ae:29:05:fa:ef:a6:8c:c8:25:06:33:e3:
             47:9b:20:34:19:45:18:fa:45:62:f8:91:4b:3f:0c:7e:35:23:
             ed:02:20:12:d1:84:72:99:bd:ba:bd:c0:cb:b8:78:86:65:2c:
             9f:74:0b:0c:bf:a6:b9:20:8d:9d:78:99:f3:8e:cc:b5:82
    
    
    
    $ openssl asn1parse -in server.crt  //ASN.1으로 분석가능 (너무길어서 생략)
    $ openssl asn1parse -in server.crt -dump  //ASN.1 BIT STRING도 보고 싶다면 
    


    • CA(Certificate Authorities)  세부분석 
    기본정보의 이해 
    1. Issuer:  인증서 발급자 
    2. Subject 인증서 실제 소유자
    Self Sign을 했으므로, 동시에 두개의 정보를 가지고 있음 
    1. Authority Key Identifier: 인증서 발급자 (Issuer) Public Key Hash Value
    2. Subject Key Identifier: 인증서 소유자 Public Key Hash Value
    3. Basic Constraints : CA 인지 아닌지 구분

    $ openssl pkey -in ca.key -noout -text  // ca.key 분석 
    Private-Key: (256 bit)
    priv:
        5e:78:6b:5b:ea:78:78:88:47:76:8c:28:e9:01:12:
        05:4c:93:fe:f0:d7:63:a7:3b:7b:3c:f4:3a:b9:ac:
        ee:8a
    pub:
        04:5d:b2:ef:15:6e:3a:f2:d0:4d:b3:aa:fa:8f:cc:
        88:9d:f6:68:4d:e0:93:29:f7:64:44:84:bb:e6:bd:
        e5:8a:7e:85:18:67:c6:84:b9:a5:67:5a:0e:e7:e9:
        c5:a9:c9:9b:10:81:c1:4e:ce:65:df:6e:e2:08:cb:
        98:3e:af:07:f3
    ASN1 OID: prime256v1
    NIST CURVE: P-256
    
    $ openssl x509 -in ca.crt -noout -text  // ca.crt 분석 
    Certificate:
        Data:
            Version: 3 (0x2)       // 인증서 Version 
            Serial Number:     // 인증서 Serial Number로 Unique하며, 매번 CA 생성시마다 다르며, 최대 20bytes 
                2b:e8:58:10:ad:b8:13:0b:6b:89:bf:97:c5:87:30:b3:5e:13:fb:88
            Signature Algorithm: ecdsa-with-SHA256               // 인증서 Signature Alogirthm 
            Issuer: C = KR, ST = SL, L = Seoul, O = Jeonghun, OU = JHLEE, CN = JeonghunCA  // 인증서 발급자 (Reference)
            Validity          // 인증서 유효기간 (10년) 
                Not Before: Jul  7 05:52:52 2020 GMT
                Not After : Jul  5 05:52:52 2030 GMT
            Subject: C = KR, ST = SL, L = Seoul, O = Jeonghun, OU = JHLEE, CN = JeonghunCA // 인증서 소유자,(발급자와 소유자 동일) 
            Subject Public Key Info:                   // 인증서 Public Key 정보 (ca.key) 
                Public Key Algorithm: id-ecPublicKey
                    Public-Key: (256 bit)          // Publickey의 SHA1 Hash값으로 아래의 확장의 Subject Key Identifier 적용  
                    pub:                           // ca.key가 동일하며 , Public Key와 Subject Key Identifier는 항상동일  
                        04:5d:b2:ef:15:6e:3a:f2:d0:4d:b3:aa:fa:8f:cc:
                        88:9d:f6:68:4d:e0:93:29:f7:64:44:84:bb:e6:bd:
                        e5:8a:7e:85:18:67:c6:84:b9:a5:67:5a:0e:e7:e9:
                        c5:a9:c9:9b:10:81:c1:4e:ce:65:df:6e:e2:08:cb:
                        98:3e:af:07:f3
                    ASN1 OID: prime256v1
                    NIST CURVE: P-256
            X509v3 extensions:       // 인증서 확장
                X509v3 Subject Key Identifier:      // 상위 Public Key의 SHA1 Hash값(20bytes)며, 상위 server.crt 의 Authority Key Id 적용 
                    F1:D2:00:25:AC:FE:65:DD:FC:F1:B7:21:83:C4:90:A9:FB:35:32:AB
                X509v3 Authority Key Identifier:   // Self Sign이므로 Subject Key Id 와 동일 
                    keyid:F1:D2:00:25:AC:FE:65:DD:FC:F1:B7:21:83:C4:90:A9:FB:35:32:AB
    
                X509v3 Basic Constraints: critical           // 인증서 CA TRUE
                    CA:TRUE
        Signature Algorithm: ecdsa-with-SHA256              // 인증서 Signature Value (SHA256 적용후 ECDSA 적용)
             30:45:02:20:44:9b:11:96:08:45:5f:ba:8e:a1:df:c9:96:aa:
             0a:88:7b:90:63:48:cc:ba:57:65:6f:3e:d6:fe:31:84:5c:f4:
             02:21:00:f1:a2:3f:c2:5e:40:e5:95:80:cb:cb:53:8c:ee:32:
             d2:c9:33:85:84:a7:60:a8:c8:d6:21:45:b0:d9:48:b7:32
    
    $ openssl asn1parse -in ca.crt  //ASN.1으로 분석가능 (너무길어서 생략)
    
    $ openssl asn1parse -in ca.crt -dump  //ASN.1 BIT STRING도 보고 싶다면 
    


    • CA의 세부사항 확인
     Subject Key Identifier 값 확인방법 
    //상위 ca.crt의 Public-Key: (256 bit) 값  65(1+32+32) Bytes 
    // 상위 ca.crt의 Public-Key 부분을 ":"로 제거하여 아래와 같이 정리
    045db2ef156e3af2d04db3aafa8fcc889df6684de09329f7644484bbe6bde58a7e851867c684b9a5675a0ee7e9c5a9c99b1081c14ece65df6ee208cb983eaf07f3
    
    // 아래 사이트에서 SHA1 Hash 값을 상위 값으로 적용하면 ca.crt의 Subject Key Identifier 와 동일 
    //ca.crt의 Subject Key Identifier:  Public Key 65 bytes SHA1 Hash Value (20bytes, 160bit) 
    f1d20025acfe65ddfcf1b72183c490a9fb3532ab

    SHA1 Hash (상위값 적용하면 동일,주의 Input Type: TEXT->HEX사용 )


    • CA의 세부항목: Signature Algorithm 의 Signature Value 
    SHA256를 적용후 256bit가 나온 결과를 ECDSA를 적용하면, R과 S는 나온다고 함 




    • CA의 Signature 테스트 방법
    1. CA에서 Public Key 만 추출 
    2. CA의 Private Key 기반으로 Signature 생성 
    3. CA의 Public Key로 검증 

    상위 2.2 에서 설명한 Certificate Signature 테스트 한 부분과 동일하며 이를 실제로 Server Certificate에서 적용하여 테스트


    OpenSSL 를 이용한 인증서의 Signature 테스트
    // CA(ca.crt)에서 Public Key 만 추출
    $ openssl x509 -pubkey -noout -in ca.crt > ca_pubkey.pem
    
    //CA의 Private Key를 이용하여 Sign하여 Signature 생성(sigfile)
    $ openssl dgst -sha256 -sign ca.key -out sigfile  server.crt
    
    //간단히 Signature file확인  (실제 인증서 Signature Value 다르며, 상위 에서 생성될때마다 아래의 값이 다름) 
    $ hd sigfile 
    or
    $ hexdump sigfile   
    
    //CA의 Public Key(ca_pubkey.pem) 와 Signature(sigfile) 이용하여 간단히 server.crt 검증  
    $ openssl dgst -verify ca_pubkey.pem -signature sigfile server.crt
    Verified OK


    ECDSA Encrypt/Decrypt 예제 


    • 관련참고링크사항

    openssl x509 manual
      https://www.openssl.org/docs/manmaster/man1/openssl-x509.html

    openssl asn1parse
      https://www.openssl.org/docs/manmaster/man1/openssl-asn1parse.html

    X.509 기본구조
      https://en.wikipedia.org/wiki/X.509#Structure_of_a_certificate

    ECDSA 기반의 CA 와 Certificate 생성방법
      https://www.erianna.com/ecdsa-certificate-authorities-and-certificates-with-openssl/

    3/29/2020

    Uboot 설정 과 Device Tree 처리방법

    1. Uboot 구성 및 설정 

    Uboot 기본 Manual
      https://www.denx.de/wiki/DULG/Manual

    Uboot 의 전체 구성 과 설정방법
      https://gitlab.denx.de/u-boot/u-boot/raw/HEAD/README


    • Uboot 의 명령어
      https://www.denx.de/wiki/view/U-Bootdoc/BasicCommandSet
      https://www.digi.com/resources/documentation/digidocs/PDFs/90000852.pdf
      https://sites.google.com/site/manisbutareed/bringing-my-beagles-to-heel/u-boot-commands
      https://sites.google.com/site/manisbutareed/bringing-my-beagles-to-heel/selected-annotated-u-boot-commands


    • Uboot 환경값
      https://sites.google.com/site/manisbutareed/bringing-my-beagles-to-heel/u-boot-environment-variables


    1.1 Uboot 와 DTB 결합구성 


    • Uboot Image 의 구성
    1. Uboot의 DTS를 DTC를 이용하여 DTB 파일생성 
    2. Uboot  Build를 진행 Uboot 파일생성
    3. cat를 이용하여 상위 두개 파일을 하나로 결합 
    4. mkimage를 이용하여 최종 Image 생성 

    DTB Image를 최종 합쳐서 Uboot Image로 만들어서 제공

    https://rocketboards.org/foswiki/Documentation/A10GSRDV1511GeneratingUBootAndUBootDeviceTree

    • Uboot Build 된곳에서 기본적인확인 
    상위 그림처럼 Uboot 와 Uboot의 DTB를 결합하여 최종 Uboot 생성

    $ cat dts/.dt.dtb.cmd  //Uboot DTB 파일 
    cmd_dts/dt.dtb := cat arch/arm/dts/imx6sx-sdb-emmc.dtb > dts/dt.dtb
    
    $ cat .u-boot-nodtb.bin.cmd  // 일반 Uboot bin 생성 (objcopy)
    cmd_u-boot-nodtb.bin := arm-poky-linux-gnueabi-objcopy --gap-fill=0xff  -j .text -j .secure_text -j .secure_data -j .rodata -j .hash -j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn -j .binman_sym_table -j .text_rest -j .dtb.init.rodata -j .efi_runtime -j .efi_runtime_rel -O binary   u-boot u-boot-nodtb.bin
    
    $ cat .u-boot-dtb.bin.cmd    //Uboot 와 DTB 결합 
    cmd_u-boot-dtb.bin := cat u-boot-nodtb.bin dts/dt.dtb > u-boot-dtb.bin
    
    $ cat .u-boot.bin.cmd      // Uboot 이름변경 및 최종 uboot
    cmd_u-boot.bin := cp u-boot-dtb.bin u-boot.bin   
    
    $ cat .u-boot.imx.cmd // 최종 u-boot image
    cmd_u-boot.imx := ./tools/mkimage -n u-boot.cfgout -T imximage -e 0x87800000 -d u-boot.bin u-boot.imx >u-boot.imx.log  && cat u-boot.imx.log
    

    Uboot 와 Kernel 는 각각 DTS 존재하며, 두 DTS가 동일하지만, Uboot의 DTB 와 Kernel DTB는 각각 별도로 사용이 되어지고 있다.

    내 개인적인 생각으로는 1st Boot Loader가 Uboot에게 전달하고, Uboot가 다시 Kernel에게 전달하여 전부 공유할 것이라고 생각했는데,
    설정을 바꿔서 어떻게 공유할 수 있는지를 알아봐야겠다.
    (환경변수 fdtcontroladdr 와  fdt_addr를 동일하게 공유)

    Device Tree Boot 기본 구조
    아래링크의 그림부분 참조
      https://ahyuo79.blogspot.com/2015/08/am437x-kernel-device-tree.html

    TI-Sitara 의 Uboot / Kernel 의 Device Tree 관련부분 복습
      https://ahyuo79.blogspot.com/2015/08/kernel-boot-kernel-device-tree.html
      https://elinux.org/Device_Tree_Reference

    Uboot 관련정보정리
      https://www.denx.de/wiki/pub/U-Boot/MiniSummitELCE2014/uboot2014_kconfig.pdf

    1.2 Uboot 와 DTB 관련소스분석 

    • Uboot fdt 확인
    => version
    U-Boot 2019.04-4.19.35-1.1.0+g4d37753 (May 13 2020 - 07:43:31 +0000)
    
    arm-poky-linux-gnueabi-gcc (GCC) 8.3.0
    GNU ld (GNU Binutils) 2.32.0.20190204
    
    => bdinfo
    arch_number = 0x00000000
    boot_params = 0x80000100
    DRAM bank   = 0x00000000
    -> start    = 0x80000000
    -> size     = 0x40000000
    baudrate    = 115200 bps
    TLB addr    = 0xbfff0000
    relocaddr   = 0xbff45000
    reloc off   = 0x38745000
    irq_sp      = 0xbdf359f0
    sp start    = 0xbdf359e0
    FB base     = 0x00000000
    Early malloc usage: fc / 400
    fdt_blob    = 0xbdf35a08  //uboot용 dtb (device tree blob) 주소
    

    • Uboot Config 설정확인 
    $ vi .config   // Uboot Config 
    ....
    #
    # Partition Types
    #
    CONFIG_PARTITIONS=y
    # CONFIG_MAC_PARTITION is not set
    CONFIG_DOS_PARTITION=y
    # CONFIG_ISO_PARTITION is not set
    # CONFIG_AMIGA_PARTITION is not set
    CONFIG_EFI_PARTITION=y
    CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=128
    CONFIG_EFI_PARTITION_ENTRIES_OFF=0
    CONFIG_PARTITION_UUIDS=y
    # CONFIG_PARTITION_TYPE_GUID is not set
    CONFIG_SUPPORT_OF_CONTROL=y
    CONFIG_DTC=y
    
    #
    # Device Tree Control
    #
    ## 아래 설정으로 Uboot에서 Device Tree 사용 (fdt 사용가능)
    CONFIG_OF_CONTROL=y          
    # CONFIG_OF_BOARD_FIXUP is not set
    # CONFIG_OF_LIVE is not set
    ## 아래 설정때문에 cat u-boot.bin u-boot.dtb >image.bin 결합 
    CONFIG_OF_SEPARATE=y
    # CONFIG_OF_EMBED is not set
    # CONFIG_OF_BOARD is not set
    # CONFIG_OF_PRIOR_STAGE is not set
    CONFIG_DEFAULT_DEVICE_TREE="imx6sx-sdb-emmc"
    # CONFIG_MULTI_DTB_FIT is not set
    CONFIG_MKIMAGE_DTC_PATH="dtc"
    
    #
    # Environment
    #
    # CONFIG_ENV_DEFAULT_NOWHERE is not set
    # CONFIG_ENV_IS_IN_EEPROM is not set
    # CONFIG_ENV_IS_IN_FAT is not set
    # CONFIG_ENV_IS_IN_EXT4 is not set
    # CONFIG_ENV_IS_IN_FLASH is not set
    CONFIG_ENV_IS_IN_MMC=y
    .....
    


    • Uboot Linker Script 
    $ vi arch/arm/cpu/u-boot.lds  
    
            .rel_dyn_end :
            {
                    *(.__rel_dyn_end)
            }
    
            .end :
            {
                    *(.__end)
            }
    
            _image_binary_end = .;
    
    //binary 로 변경시 아래부분은 필요없음 
    
            /*
             * Deprecated: this MMU section is used by pxa at present but
             * should not be used by new boards/CPUs.
             */
            . = ALIGN(4096);
            .mmutable : {
                    *(.mmutable)
            }
    .....
    $ vi u-boot.map // System.map 재확인 
    

    • Uboot Source 확인
    Uboot Config 기반으로 소스확인

    $ vi common/board_r.c
    ......
    static init_fnc_t init_sequence_r[] = {
            initr_trace,
            initr_reloc,
    ...
    #ifdef CONFIG_MMC
            initr_mmc,
    #endif
            initr_env,
    ....
            run_main_loop,
    };
    
    static int initr_env(void)
    {
            /* initialize environment */
            if (should_load_env())
                    env_relocate();
            else
                    set_default_env(NULL, 0);
    // 매번 Booting 때마다 fdtcontroladdr 변수설정하기 때문에 User가 변경해도 소용없음 
    // Uboot에서 printenv로 확인가능하며 상위 CONFIG확인 
    #ifdef CONFIG_OF_CONTROL
            env_set_hex("fdtcontroladdr",
                        (unsigned long)map_to_sysmem(gd->fdt_blob));  
    #endif
    
            /* Initialize from environment */
            load_addr = env_get_ulong("loadaddr", 16, load_addr);
    
            return 0;
    }
    

    상위 설정대로 했을 경우 아래 bold 체가 실행

    $ vi lib/fdtdec.c  // Uboot의 dtb부분 처리를 이해가능 
    
    #if defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE)
    /*
     * For CONFIG_OF_SEPARATE, the board may optionally implement this to
     * provide and/or fixup the fdt.
     */
    __weak void *board_fdt_blob_setup(void)
    {
            void *fdt_blob = NULL;
    #ifdef CONFIG_SPL_BUILD
            /* FDT is at end of BSS unless it is in a different memory region */
            if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
                    fdt_blob = (ulong *)&_image_binary_end;
            else
                    fdt_blob = (ulong *)&__bss_end;
    #else
            //CONFIG_OF_SEPARATE만 사용해서 uboot 끝에서 fdt를 가져옴 (Linker Script 참조)
            /* FDT is at end of image */
            fdt_blob = (ulong *)&_end;     
    #endif
            return fdt_blob;
    }
    #endif
    
    int fdtdec_setup(void)
    {
    #if CONFIG_IS_ENABLED(OF_CONTROL)   // 현재설정 CONFIG_OF_CONTROL=y
    
    # if CONFIG_IS_ENABLED(MULTI_DTB_FIT) // 현재 미설정 # CONFIG_MULTI_DTB_FIT is not set
            void *fdt_blob;
    # endif
    
    # ifdef CONFIG_OF_EMBED  // 현재 미설정 # CONFIG_OF_EMBED is not set
            /* Get a pointer to the FDT */
    #  ifdef CONFIG_SPL_BUILD // 현재 미설정 
            gd->fdt_blob = __dtb_dt_spl_begin;
    #  else
            gd->fdt_blob = __dtb_dt_begin;
    #  endif
    # elif defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE) // 현재 이부분만 실행 
            /* Allow the board to override the fdt address. */
            gd->fdt_blob = board_fdt_blob_setup();  // 상위함수 참고 CONFIG_OF_BOARD는 미설정
    # elif defined(CONFIG_OF_HOSTFILE)
            if (sandbox_read_fdt_from_file()) {
                    puts("Failed to read control FDT\n");
                    return -1;
            }
    # endif
    # ifndef CONFIG_SPL_BUILD  // 현재 미설정 
            /* Allow the early environment to override the fdt address */
    #  if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)   // 현재 미설정 # CONFIG_OF_PRIOR_STAGE is not set
            gd->fdt_blob = (void *)prior_stage_fdt_address;
    #  else
    // 상위에서 설정된 gd->fdt_blob 변수 fdtcontroladdr의 기본값으로 읽어옴 
    //bdinfo 와 printenv 확인가능 
            gd->fdt_blob = map_sysmem
                    (env_get_ulong("fdtcontroladdr", 16,
                                   (unsigned long)map_to_sysmem(gd->fdt_blob)), 0); 
    #  endif
    # endif
    
    # if CONFIG_IS_ENABLED(MULTI_DTB_FIT)   // 현재미설정 # CONFIG_MULTI_DTB_FIT is not set
            /*
             * Try and uncompress the blob.
             * Unfortunately there is no way to know how big the input blob really
             * is. So let us set the maximum input size arbitrarily high. 16MB
             * ought to be more than enough for packed DTBs.
             */
            if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0)
                    gd->fdt_blob = fdt_blob;
    
            /*
             * Check if blob is a FIT images containings DTBs.
             * If so, pick the most relevant
             */
            fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
            if (fdt_blob) {
                    gd->multi_dtb_fit = gd->fdt_blob;
                    gd->fdt_blob = fdt_blob;
            }
    
    # endif
    #endif
    
            return fdtdec_prepare_fdt();
    }
    

    이전의 Uboot 관련소스
      https://lists.denx.de/pipermail/u-boot/2012-July/127516.html
      https://gitlab.labs.nic.cz/turris/u-boot-turris/commit/eea63e05d0b7f54e7aa39725015483972c71cb3c

    • Uboot의 DTB  설정확인
    $ vi arch/arm/dts/Makefile
    ....
    dtb-$(CONFIG_MX6SX) += \
            imx6sx-14x14-arm2.dtb \
            imx6sx-17x17-arm2.dtb \
            imx6sx-17x17-arm2-ecspi.dtb \
            imx6sx-17x17-arm2-gpmi-weim.dtb \
            imx6sx-19x19-arm2.dtb \
            imx6sx-19x19-arm2-ecspi.dtb \
            imx6sx-19x19-arm2-gpmi-weim.dtb \
            imx6sx-sabreauto.dtb \
            imx6sx-sdb.dtb \
            imx6sx-sdb-emmc.dtb
    .....
    


    1.3 Uboot 의 Flattened Device Tree (FDT)

    Uboot는 DTB File을 Memory 에 Load하여 기본 확인가능하며, 이를 수정도 가능한 명령이 fdt 명령어이다.
    uImage 에서 사용하게 될 dtb, 즉 kernel 용 dtb를 fdt 명령어를 이용하여 이를 확인해보자.

    fdt 명령어 설명 (세부명령어 참조)
      https://www.denx.de/wiki/view/DULG/UBootCmdFDT#Section_5.9.7.2.
      https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841676/U-Boot+Flattened+Device+Tree

    • Uboot 에서 Kernel의 DTB 정보확인 
    Kernel에서 사용하게될 DTB 정보확인

    =>pri
    ...
    mmcdev=3
    mmcpart=1
    fdt_addr=0x83000000
    fdt_file=undefined.dtb
    loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}   
    .....
    => setenv fdt_file imx6sx-sdb-emmc.dtb  //DTB File 이름변경 
    
    => run loadfdt        //상위 명령어 실행 (eMMC or SDcard의 Device의 Partition에서 File 읽기 
    49954 bytes read in 15 ms (3.2 MiB/s)
    
    => fdt addr ${fdt_addr}  // FDT address 설정 
    
    => fdt list  // DTB 파일을 볼수 있음 
    ....
    => fdt print // DTB 파일을 세부적으로 확인 
    ....
    

    1.4 Uboot Env 분석 및 Hush Shell Script 확장 

    i.MX6의 경우 이전에 TI의 Uboot Env보다 좀 더 잘 구성이 되어있어 이부분을 간단정리

    => pri
    baudrate=115200
    boot_fdt=try
    bootargs=console=ttymxc0,115200 rdinit=/linuxrc clk_ignore_unused
    bootcmd=run findfdt; mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else run netboot; fi
    bootcmd_mfg=run mfgtool_args;if iminfo ${initrd_addr}; then if test ${tee} = yes; then bootm ${tee_addr} ${initrd_addr} ${fdt_addr}; else bootz ${loadaddr} ${initrd_addr} ${fdt_addr}; fi; else echo "Run fastboot ..."; fastboot 0; fi;
    bootdelay=3
    bootscript=echo Running bootscript from mmc ...; source   // source command를 이용하여 boot.scr 실행 (default loadaddr) 
    console=ttymxc0
    emmc_ack=0
    emmc_dev=3
    eth1addr=c2:42:5a:9f:cd:09
    ethact=ethernet@02188000
    ethaddr=26:E1:2C:C4:C7:C6
    ethprime=eth0
    fastboot_bytes=adc00
    fastboot_dev=mmc
    fdt_addr=0x83000000       // Kernel용 DTB 주소 (DRAM) 
    fdt_file=undefined        // Kernel용 DTB File 이름
    fdt_high=0xffffffff       // DTB MAX DRAM MAX 
    fdtcontroladdr=bdf35a08  // Uboot 용 DTB 주소 (DRAM)  
    filesize=adc00
    findfdt=if test $fdt_file = undefined; then setenv fdt_file imx6sx-sdb-emmc.dtb; fi;
    image=zImage
    initrd_addr=0x86800000
    initrd_high=0xffffffff
    ip_dyn=yes
    kboot=bootz
    loadaddr=0x80800000
    loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};  // eMMC에서 bootscript 읽어서 쉽게확장
    loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file} // Kernel DTB File 읽기
    loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}  // Kernel Image
    loadm4image=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${m4image} // qspi용 Kernel Image로 추정
    loadtee=fatload mmc ${mmcdev}:${mmcpart} ${tee_addr} ${tee_file}  // 보안 boot 
    m4_qspi_cs=2
    m4boot=sf probe 1:${m4_qspi_cs}; bootaux 0x78000000
    m4image=m4_qspi.bin
    mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc clk_ignore_unused
    mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
    mmcautodetect=yes
    mmcboot=echo Booting from mmc ...; run mmcargs; if test ${tee} = yes; then run loadfdt; run loadtee; bootm ${tee_addr} - ${fdt_addr}; else if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi; fi;
    mmcdev=3
    mmcpart=1
    mmcroot=/dev/mmcblk3p2 rootwait rw
    netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
    netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${image}; if test ${tee} = yes; then ${get_cmd} ${tee_addr} ${tee_file}; ${get_cmd} ${fdt_addr} ${fdt_file}; bootm ${tee_addr} - ${fdt_addr}; else if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdt_file}; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;fi;
    panel=Hannstar-XGA
    script=boot.scr  // FAT에서 boot.scr를 만들어 설정확장
    sd_dev=3
    serial#=121a59d4f21fe636
    soc_type=imx6sx
    tee=no
    tee_addr=0x84000000
    tee_file=uTee-6sxsdb
    update_m4_from_sd=if sf probe 1:${m4_qspi_cs}; then if run loadm4image; then setexpr fw_sz ${filesize} + 0xffff; setexpr fw_sz ${fw_sz} / 0x10000; setexpr fw_sz ${fw_sz} * 0x10000; sf erase 0x0 ${fw_sz}; sf write ${loadaddr} 0x0 ${filesize}; fi; fi


    • i.MX6의 경우 HW bootmode에 따라 bootcmd의 실행변경
    1. bootcmd: 일반 boot  Mode
    2. bootcmd_mfg: Download Mode (uuu라는 Program을 이용하여 fastboot이용)

    • Download Mode (fastboot이용)
    i.MX6는 Download Mode 일 경우 USB를 통해서 Window/Linux의 uuu(mfgtools) Program을 이용하여 boot가 가능하다.
    PC (USB Host) / i.MX6 (USB Device) 로 동작이되며, Uboot에서 fastboot를 이용하여 usb로 각 Data를 Download를 하고, eMMC or SDCard를 Write를 진행한다.
    PC용 fastboot로는 연결해보지 못하고 오직 uuu라는 Program만 사용해봄

    • bootcmd 일 경우 
    상위를 간단히 분석을 해보면 확장을 위해서 별도의 Uboot Script 파일을 읽어 User에서 Uboot의 설정을 변경가능하도록 만들었다.

    • loadbootscript (확장의 용이성)
    Linux의 User에서 수정가능한 Uboot Script(boot.scr)가 존재하며, Linux User는 Uboot Env를 쉽게 이를 이용하여 변경이 가능하다.

    TI-Sitara Uboot Script 및 Device Tree 설정
      https://ahyuo79.blogspot.com/2015/08/uboot-script-device-tree.html


    1.5 Uboot Env 값 고정값으로 설정 

    Env값들 중 변경 불가능 값들이 존재하여 관련된 소스분석 아래와 같이 board init 할때 마다 env_set 관련 function을 이용하여 직접 설정

    $ cd uboot
    $ vi include/configs/mx6sxsabresd.h   // 기본적인 uboot의 default env 값으로 saveenv 로 user가 각각 변경가능
    
    #define CONFIG_EXTRA_ENV_SETTINGS \       //default env 값들 (saveenv 변경가능하지만, 변경불가능한 값 원인분석)
    ...............
    
    #define CONFIG_BOOTCOMMAND \             // bootcmd 값  (saveenv 변경가능) 
               "run findfdt; " \
               "mmc dev ${mmcdev}; if mmc rescan; then " \
                       "if run loadbootscript; then " \
                               "run bootscript; " \
                       "else " \
                               "if run loadimage; then " \
                                       "run mmcboot; " \
                               "else run netboot; " \
                               "fi; " \
                       "fi; " \
               "else run netboot; fi"
    
    //mmcdev 와 mmcroot의 경우 saveenv로 변경을해도 board_init 할때마다 새로설정됨  
    $ vi board/freescale/common/mmc.c  
    ....
    void board_late_mmc_env_init(void)
    {
            char cmd[32];
            char mmcblk[32];
            u32 dev_no = mmc_get_env_dev();
    
            if (!check_mmc_autodetect())
                    return;
    
    //mmcdev 값 고정  , saveenv로 변경해도 기본값으로 설정 
            env_set_ulong("mmcdev", dev_no);
    
    //mmcroot 값 고정 , saveenv로 변경해도 기본값으로 설정 
            /* Set mmcblk env */
            sprintf(mmcblk, "/dev/mmcblk%dp2 rootwait rw",
                    mmc_map_to_kernel_blk(dev_no));
            env_set("mmcroot", mmcblk);
    
            sprintf(cmd, "mmc dev %d", dev_no);
            run_command(cmd, 0);
    }
    


    2. Uboot 의 Command Script 관리 

    예전의 Uboot 보다 점점 많은 명령어를 지원해주고 있으며, fastboot를 비롯하여, 각종 filesystem도 마음대로 접근이 가능하며,
    다양한 Hardware Interface도 지원을 해주고 있어 Hush shell 를 잘 이용하면 일반 Shell Script 못지않게 잘 사용할 수 있을 것 같다.

    각종 사용되어지는 Image 관리부터 각각의 Interface check 기능 및다양한 Program을 쉽게 작성이 가능할 것 같다.

    Hush Shell Script
      https://sites.google.com/site/manisbutareed/bringing-my-beagles-to-heel/5-to-be-continued

    // Android의 fastboot 기능 
    fastboot  - run as a fastboot usb or udp device
    // Partition 
    gpt       - GUID Partition Table
    part      - disk partition related commands
    
    // File system 관리 명령어 
    fstype    - Look up a filesystem type
    fatsize   - determine a file's size
    
    ext2load  - load binary file from a Ext2 filesystem
    ext2ls    - list files in a directory (default /)
    ext4load  - load binary file from a Ext4 filesystem
    ext4ls    - list files in a directory (default /)
    ext4size  - determine a file's size
    ext4write - create a file in the root directory
    
    fatinfo   - print information about filesystem
    fatload   - load binary file from a dos filesystem
    fatls     - list files in a directory (default /)
    fatmkdir  - create a directory
    fatrm     - delete a file
    fatsize   - determine a file's size
    fatwrite  - write file into a dos filesystem
    
    // DTB 관리 
    fdt       - flattened device tree utility commands
    


    2.1  Uboot의 mmc command 사용


    => mmc
    mmc - MMC sub system
    
    Usage:
    mmc info - display info of the current MMC device
    mmc read addr blk# cnt
    mmc write addr blk# cnt
    mmc erase blk# cnt
    mmc rescan
    mmc part - lists available partition on current mmc device
    mmc dev [dev] [part] - show or set current mmc device [partition]
    mmc list - lists available devices
    mmc hwpartition [args...] - does hardware partitioning
      arguments (sizes in 512-byte blocks):
        [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes
        [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition
        [check|set|complete] - mode, complete set partitioning completed
      WARNING: Partitioning is a write-once setting once it is set to complete.
      Power cycling is required to initialize partitions after set to complete.
    mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode
     - Set the BOOT_BUS_WIDTH field of the specified device
    mmc bootpart-resize   
     - Change sizes of boot and RPMB partitions of specified device
    mmc partconf dev [boot_ack boot_partition partition_access]
     - Show or change the bits of the PARTITION_CONFIG field of the specified device
    mmc rst-function dev value
     - Change the RST_n_FUNCTION field of the specified device
       WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.
    mmc setdsr  - set DSR register value
    

    MMC 사용예제
      https://forums.xilinx.com/t5/ACAP-and-SoC-Boot-and/U-boot-Mmc-read-write/td-p/891742

    • mmc 기본확인
    => mmc list
    FSL_SDHC: 1
    FSL_SDHC: 2 (SD)
    FSL_SDHC: 3 (eMMC)
    
    => mmc dev 3   //mmc device 선택 
    switch to partitions #0, OK
    mmc3(part 0) is current device
    
    => mmc part
    
    Partition Map for MMC device 3  --   Partition Type: DOS
    
    Part    Start Sector    Num Sectors     UUID            Type
      1     8192            45668           304dec68-01     0c Boot
      2     57344          445688          304dec68-02     83
      3     507904          524288          304dec68-03     83
    
    => mmc dev 2  //mmc device 선택 
    switch to partitions #0, OK
    mmc2 is current device
    
    => mmc part
    
    Partition Map for MMC device 2  --   Partition Type: DOS
    
    Part    Start Sector    Num Sectors     UUID            Type
      1     129             3911551         02751898-01     0c
    


    • mmc erase/write/read 방법
    //SD Card의 Partition1 에서 File read 
    => fatload mmc 2:1 ${loadaddr} core-lora-image-imx6sxsabresd.wic 
    528482304 bytes read in 35944 ms (14 MiB/s)
    
    => mmc dev 3   //mmc device 선택 
    switch to partitions #0, OK
    mmc3(part 0) is current device
    
    => pri loadaddr
    loadaddr=0x80800000
    
    //0x82400000  = 0x80800000 + 0x1C00000 ( 57344*512)
    // Start Sector 0xE000(57344) 
    // Num Sectors 0x6CCF8‬(445688)
    // mmc read/write/erase HEX로 밖에 동작이 안됨 
    
    => mmc erase 0xE000 0x6CCF8‬ //eMMC erase
    MMC erase: dev # 3, block # 57344, count 445688 ...
    
    => mmc write 0x82400000 0xE000 0x6CCF8‬ //eMMC Write 
    MMC write: dev # 3, block # 57344, count 445688 ... 445688 blocks written: OK
    
    => mmc read 0x82400000 0xE000 0x6CCF8‬ //eMMC Write 
    MMC read: dev # 3, block # 57344, count 445688 ... 445688 blocks read: OK
    

    상위 정보는 linux application에서 fdisk -l 의 정보와 동일하며, image는 dd를 이용하여 편집가능

    2.2 Uboot Script 생성

    상위에서 사용했던 방법들을 간단히 정리하여 Script로 만들어서 이를 확장하는 방법을 알아보자.


    • 환경변수로 분할한 후 마지막에 연결
    SDcard에서 image를 읽고 write한 후 bootscript 삭제
    $ vi myboot0.cmd
    setenv upgrade_read fatload mmc 2:1 ${loadaddr} core-lora-image-imx6sxsabresd.wic 
    setenv upgrade_write mmc write 0x82400000 0xE000 0x6CCF8‬ 
    setenv upgrade_remove fatrm mmc 2:1 ${script}
    setenv upgradelog_start         echo ======== Simple Upgrade Script
    setenv upgradelog_success       echo ======== Succeed to upgrade the firmware
    setenv upgradelog_success_read  echo ======== Succeed to read the firmware
    setenv upgradelog_success_write echo ======== Succeed to wirte the firmware
    setenv upgradelog_fail_read     echo ======== Failed to read a firmware file 
    setenv upgradelog_fail_write    echo ======== Failed to write a firmware file 
    setenv upgrade_targets read write remove 
    setenv upgrade_loop "for target in ${upgrade_targets}; do run upgrade_${target}; done" 
    setenv upgrade_select "run upgradelog_start; if run upgrade_read; then if run upgrade_write; then run upgrade_remove; else run upgradelog_fail_write; fi; else run upgradelog_fail_read; fi"
    run upgrade_select
    


    • 전체순차적으로 실행 
    SDcard 삽입시 계속 Loop에 지속적으로 실행되며, SD Card 제거시 동작 중지
    $ vi myboot1.cmd
    echo ======== Simple Version Upgrade Script;
    setenv targetaddr ${loadaddr};
    if test $version = 1; then
       echo "======== checked your firmware version";
       setenv upgrade_read fatload mmc 2:1 ${loadaddr} core-lora-image-imx6sxsabresd.wic
       setenv upgrade_write mmc write 0x82400000 0xE000 0x6CCF8
       if run upgrade_read; then
          echo "======== Ok found a SD card upgrade file";
          echo "======== Start to upgrade a firmware";
    
          if run upgrade_write; then
             echo "======== Ok write the firmware into eMMC";
             setenv version 2; 
             mw  ${targetaddr} 0 100;
             mw  ${targetaddr} 0x43435553 1;
             setexpr targetaddr $targetaddr + 4;
             mw  ${targetaddr} 0x20535345 1;
             fatwrite mmc 2:1 ${loadaddr} result.txt 8         
          else
             echo "======== failed to write the image to eMMC";
             mw  ${targetaddr} 0 100;
             mw  ${targetaddr} 0x4c494146 1;
             setexpr targetaddr $targetaddr + 4;
             mw  ${targetaddr} 0x20 1;
             fatwrite mmc 2:1 ${loadaddr} result.txt
             setenv version 0
          fi
       else
          echo "======== failed to read the image from SD card";
          mw  ${targetaddr} 0 100;
          mw  ${targetaddr} 0x4c494146 1;
          setexpr targetaddr $targetaddr + 4;
          mw  ${targetaddr} 0x20 1;
          setenv version 0;
       fi
    else
       echo "======== its same version";
       mw  ${targetaddr} 0 100;
       mw  ${targetaddr} 0x454d4153 1;
       setexpr targetaddr $targetaddr + 4;
       mw  ${targetaddr} 0x52455620 1;
       setexpr targetaddr $targetaddr + 4;
       mw  ${targetaddr} 0x4e4f4953 1;
       fatwrite mmc 2:1 ${loadaddr} result.txt
    fi
    saveenv;
    reset;
    
    boot script example
      https://boundarydevices.com/boot-scripts-for-main-line-u-boot-on-i-mx6/


    • boot scirpt 생성

    아래와 같이 기본이 PowerPC로 되어있으므로, 가능하다면, ARM으로 변경해서 사용하자. (아래와 같이 사용해도 동작가능)

    $ mkimage -T script -C none -n 'Uboot Script File' -d myboot0.cmd boot.scr
    Image Name:   Uboot Script File
    Created:      Fri May 15 17:00:50 2020
    Image Type:   PowerPC Linux Script (uncompressed)
    Data Size:    271 Bytes = 0.26 kB = 0.00 MB
    Load Address: 00000000
    Entry Point:  00000000
    Contents:
       Image 0: 263 Bytes = 0.26 kB = 0.00 MB
    


    $ mkimage -T script -C none -n 'Uboot Script File' -d myboot1.cmd boot.scr
    Image Name:   Uboot Script File
    Created:      Mon May 18 10:56:40 2020
    Image Type:   PowerPC Linux Script (uncompressed)
    Data Size:    979 Bytes = 0.96 kB = 0.00 MB
    Load Address: 00000000
    Entry Point:  00000000
    Contents:
       Image 0: 971 Bytes = 0.95 kB = 0.00 MB
    


    • boot script 적용

    => setenv version 1 // version 입력
    => setenv loadbootscript fatload mmc 2:1 ${loadaddr} ${script}; // SD Card Read로 변경 
    => saveenv
    => reset
    
    setenv loadbootscript fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
    

      https://www.denx.de/wiki/view/DULG/UBootScripts

    이를 이용하여 간단히 Upgrade script 도 간단히 만들수 있다.