SHA-2 단계별 작업 방법(SHA-256)


게시물How SHA-2 Works Step-By-Step (SHA-256)이 먼저 Qvault에 올라왔다.
SHA-2(안전 해시 알고리즘 2), 그 중에서 SHA-256은 그 중의 일부이며 가장 유행하는 hashing algorithms 중의 하나이다.본고에서 우리는 가능한 한 간단하게 알고리즘의 모든 절차를 분해하고 실제 예시를 수동으로 완성할 것이다.
SHA-2는 안전성broken down like SHA-1과 속도가 없는 것으로 유명하다.keys are not being generated의 상황에서 예를 들어 비트코인 발굴, SHA-2와 같은 빠른 산열 알고리즘은 통상적으로 주도적인 위치를 차지한다.

해시 함수는 무엇입니까?


산열 함수에 대한 일반적인 정보를 더 알고 싶으면 here 를 읽으십시오.즉, 앞으로 발전하기 위해 해시 함수의 세 가지 주요 용도를 되돌아보자.
  • 데이터에 대한 확정적 교란
  • 모든 길이의 입력을 받아들여 고정 길이를 출력한 결과
  • 데이터를 거꾸로 조작할 수 없다.출력에서 가져오기를 내보낼 수 없음
  • SHA-2와 SHA-256


    SHA-2는 알고리즘으로 데이터를 어떻게 산열하는지에 대한 일반화 사상이다.SHA-256은 SHA-2 알고리즘 동작을 정의하는 추가 상수를 설정합니다.상수 중 하나는 출력 크기입니다.256 및 512는 각각의 출력 요약 크기(비트)를 나타냅니다.
    SHA-256의 예제를 살펴보겠습니다.

    SHA-256 "안녕하세요, 세상";1단계 – 사전 처리

  • "hello world"를 바이너리로 변환:
  • 01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
    01110010 01101100 01100100
    
  • 추가 단일 1:
  • 01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
    01110010 01101100 01100100 1
    
  • 데이터가 64비트 미만인 512 배수가 될 때까지 0으로 채웁니다.
  • 01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
    01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    
    
  • 끝에 64비트를 추가하는데 그 중 64비트는 big-endian 정수로 이진법 원본 입력의 길이를 나타낸다.우리의 예에서 88, 또는 2진법,'1011000'.
  • 01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
    01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    00000000 00000000 00000000 00000000 00000000 00000000 00000000 01011000
    
    지금 우리는 입력이 생겼는데, 그것은 항상 512로 정리될 수 있다.

    2단계 – 해시 값 초기화(h)


    이제 8개의 산열 값을 만듭니다.이것들은 하드 인코딩 상수로 상위 8개 소수 제곱근 분수 부분의 상위 32위를 나타낸다. 2, 3, 5, 7, 11, 13, 17, 19
    h0 := 0x6a09e667
    h1 := 0xbb67ae85
    h2 := 0x3c6ef372
    h3 := 0xa54ff53a
    h4 := 0x510e527f
    h5 := 0x9b05688c
    h6 := 0x1f83d9ab
    h7 := 0x5be0cd19
    

    3단계 – 반올림 상수 초기화(k)


    단계 2와 유사하게 상수를 만들고 있습니다.이번에는 64개다.각 값(0-63)은 상위 64개의 소수(2-311)의 입방근 분수 부분의 상위 32자리입니다.
    0x428a2f98 0x71374491 0xb5c0fbcf 0xe9b5dba5 0x3956c25b 0x59f111f1 0x923f82a4 0xab1c5ed5
    0xd807aa98 0x12835b01 0x243185be 0x550c7dc3 0x72be5d74 0x80deb1fe 0x9bdc06a7 0xc19bf174
    0xe49b69c1 0xefbe4786 0x0fc19dc6 0x240ca1cc 0x2de92c6f 0x4a7484aa 0x5cb0a9dc 0x76f988da
    0x983e5152 0xa831c66d 0xb00327c8 0xbf597fc7 0xc6e00bf3 0xd5a79147 0x06ca6351 0x14292967
    0x27b70a85 0x2e1b2138 0x4d2c6dfc 0x53380d13 0x650a7354 0x766a0abb 0x81c2c92e 0x92722c85
    0xa2bfe8a1 0xa81a664b 0xc24b8b70 0xc76c51a3 0xd192e819 0xd6990624 0xf40e3585 0x106aa070
    0x19a4c116 0x1e376c08 0x2748774c 0x34b0bcb5 0x391c0cb3 0x4ed8aa4a 0x5b9cca4f 0x682e6ff3
    0x748f82ee 0x78a5636f 0x84c87814 0x8cc70208 0x90befffa 0xa4506ceb 0xbef9a3f7 0xc67178f2
    

    4단계 – 블록 사이클


    입력한 각 512비트 블록에 대해 다음 절차를 수행합니다.우리의 예에서'hello world'는 매우 짧기 때문에 우리는 단지 한 조각뿐이다.순환의 매번 교체에서, 우리는 변이 산열치 h0-h7을 변환할 것이며, 이것은 최종 출력이 될 것이다.

    5단계 – 메시지 계획 작성(w)

  • 단계 1의 입력 데이터를 새 그룹에 복사합니다. 항목마다 32자입니다.
  • 01101000011001010110110001101100 01101111001000000111011101101111
    01110010011011000110010010000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000001011000
    
  • 초기화 0 글자 48개를 더하면 우리는 하나의 수조 w[0...63]를 얻을 수 있다
  • 01101000011001010110110001101100 01101111001000000111011101101111
    01110010011011000110010010000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000001011000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    ...
    ...
    00000000000000000000000000000000 00000000000000000000000000000000
    
  • 다음 알고리즘을 사용하여 그룹 끝에 있는 0ed 인덱스를 수정합니다.
  • w[16.63]의 i:
  • s0=(w[i-15]rightrotate 7)xor(w[i-15]rightrotate 18)xor(w[i-15]rightshift 3)
  • s1=(w[i-2]rightrotate 17)xor(w[i-2]rightrotate 19)xor(w[i-2]rightshift 10)
  • w[i]=w[i-16]+s0+w[i-7]+s1
  • w[16]가 어떻게 일을 하는지 봅시다.
    w[1] rightrotate 7:
      01101111001000000111011101101111 -> 11011110110111100100000011101110
    w[1] rightrotate 18:
      01101111001000000111011101101111 -> 00011101110110111101101111001000
    w[1] rightshift 3:
      01101111001000000111011101101111 -> 00001101111001000000111011101101
    
    s0 = 11011110110111100100000011101110 XOR 00011101110110111101101111001000 XOR 00001101111001000000111011101101
    
    s0 = 11001110111000011001010111001011
    
    w[14] rightrotate 17:
      00000000000000000000000000000000 -> 00000000000000000000000000000000
    w[14] rightrotate19:
      00000000000000000000000000000000 -> 00000000000000000000000000000000
    w[14] rightshift 10:
      00000000000000000000000000000000 -> 00000000000000000000000000000000
    
    s1 = 00000000000000000000000000000000 XOR 00000000000000000000000000000000 XOR 00000000000000000000000000000000
    
    s1 = 00000000000000000000000000000000
    
    w[16] = w[0] + s0 + w[9] + s1
    
    w[16] = 01101000011001010110110001101100 + 11001110111000011001010111001011 + 00000000000000000000000000000000 + 00000000000000000000000000000000
    
    // addition is calculated modulo 2^32
    
    w[16] = 00110111010001110000001000110111
    
    
    이것은 우리에게 64개의 단어의 메시지 시간표를 남겼다 (w):
    01101000011001010110110001101100 01101111001000000111011101101111
    01110010011011000110010010000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000000000000
    00000000000000000000000000000000 00000000000000000000000001011000
    00110111010001110000001000110111 10000110110100001100000000110001
    11010011101111010001000100001011 01111000001111110100011110000010
    00101010100100000111110011101101 01001011001011110111110011001001
    00110001111000011001010001011101 10001001001101100100100101100100
    01111111011110100000011011011010 11000001011110011010100100111010
    10111011111010001111011001010101 00001100000110101110001111100110
    10110000111111100000110101111101 01011111011011100101010110010011
    00000000100010011001101101010010 00000111111100011100101010010100
    00111011010111111110010111010110 01101000011001010110001011100110
    11001000010011100000101010011110 00000110101011111001101100100101
    10010010111011110110010011010111 01100011111110010101111001011010
    11100011000101100110011111010111 10000100001110111101111000010110
    11101110111011001010100001011011 10100000010011111111001000100001
    11111001000110001010110110111000 00010100101010001001001000011001
    00010000100001000101001100011101 01100000100100111110000011001101
    10000011000000110101111111101001 11010101101011100111100100111000
    00111001001111110000010110101101 11111011010010110001101111101111
    11101011011101011111111100101001 01101010001101101001010100110100
    00100010111111001001110011011000 10101001011101000000110100101011
    01100000110011110011100010000101 11000100101011001001100000111010
    00010001010000101111110110101101 10110000101100000001110111011001
    10011000111100001100001101101111 01110010000101111011100000011110 10100010110101000110011110011010 00000001000011111001100101111011
    11111100000101110100111100001010 11000010110000101110101100010110
    

    6단계 – 압축

  • 변수 a, b, c, d, e, f, g, h를 초기화하고 이를 각각 현재 해시 값으로 설정한다.h0、h1、h2、h3、h4、h5、h6、h7
  • 압축 순환을 실행합니다.압축 순환은 a...h의 값을 변경합니다. 압축 순환은 다음과 같습니다.
  • 0에서 63까지의 i
  • S1=(e rightrotate 6)xor(e rightrotate 11)xor(e rightrotate 25)
  • ch= (e와 f) 또는 (e가 아님) 및 g
  • temp1=h+S1+ch+k[i]+w[i]
  • S0=(a rightrotate 2)xor(a rightrotate 13)xor(a rightrotate 22)
  • maj=(a와 b)xor(a와 c)xor(b와 c)
  • temp2:=S0+maj
  • h=g
  • g=f
  • e=d+temp1
  • d=c
  • c=b
  • b=a
  • a=temp1+temp2
  • 모든 덧셈을 계산하는 첫 번째 교체를 진행합니다modulo 2^32.
    a = 0x6a09e667 = 01101010000010011110011001100111
    b = 0xbb67ae85 = 10111011011001111010111010000101
    c = 0x3c6ef372 = 00111100011011101111001101110010
    d = 0xa54ff53a = 10100101010011111111010100111010
    e = 0x510e527f = 01010001000011100101001001111111
    f = 0x9b05688c = 10011011000001010110100010001100
    g = 0x1f83d9ab = 00011111100000111101100110101011
    h = 0x5be0cd19 = 01011011111000001100110100011001
    
    e rightrotate 6:
      01010001000011100101001001111111 -> 11111101010001000011100101001001
    e rightrotate 11:
      01010001000011100101001001111111 -> 01001111111010100010000111001010
    e rightrotate 25:
      01010001000011100101001001111111 -> 10000111001010010011111110101000
    S1 = 11111101010001000011100101001001 XOR 01001111111010100010000111001010 XOR 10000111001010010011111110101000
    S1 = 00110101100001110010011100101011
    
    e and f:
        01010001000011100101001001111111
      & 10011011000001010110100010001100 =
        00010001000001000100000000001100
    not e:
      01010001000011100101001001111111 -> 10101110111100011010110110000000
    (not e) and g:
        10101110111100011010110110000000
      & 00011111100000111101100110101011 =
        00001110100000011000100110000000
    ch = (e and f) xor ((not e) and g)
       = 00010001000001000100000000001100 xor 00001110100000011000100110000000
       = 00011111100001011100100110001100
    
    // k[i] is the round constant
    // w[i] is the batch
    temp1 = h + S1 + ch + k[i] + w[i]
    temp1 = 01011011111000001100110100011001 + 00110101100001110010011100101011 + 00011111100001011100100110001100 + 1000010100010100010111110011000 + 01101000011001010110110001101100
    temp1 = 01011011110111010101100111010100
    
    a rightrotate 2:
      01101010000010011110011001100111 -> 11011010100000100111100110011001
    a rightrotate 13:
      01101010000010011110011001100111 -> 00110011001110110101000001001111
    a rightrotate 22:
      01101010000010011110011001100111 -> 00100111100110011001110110101000
    S0 = 11011010100000100111100110011001 XOR 00110011001110110101000001001111 XOR 00100111100110011001110110101000
    S0 = 11001110001000001011010001111110
    
    a and b:
        01101010000010011110011001100111
      & 10111011011001111010111010000101 =
        00101010000000011010011000000101
    a and c:
        01101010000010011110011001100111
      & 00111100011011101111001101110010 =
        00101000000010001110001001100010
    b and c:
        10111011011001111010111010000101
      & 00111100011011101111001101110010 =
        00111000011001101010001000000000
    maj = (a and b) xor (a and c) xor (b and c)
        = 00101010000000011010011000000101 xor 00101000000010001110001001100010 xor 00111000011001101010001000000000 
        = 00111010011011111110011001100111
    
    temp2 = S0 + maj
          = 11001110001000001011010001111110 + 00111010011011111110011001100111
          = 00001000100100001001101011100101
    
    h = 00011111100000111101100110101011
    g = 10011011000001010110100010001100
    f = 01010001000011100101001001111111
    e = 10100101010011111111010100111010 + 01011011110111010101100111010100
      = 00000001001011010100111100001110
    d = 00111100011011101111001101110010
    c = 10111011011001111010111010000101
    b = 01101010000010011110011001100111
    a = 01011011110111010101100111010100 + 00001000100100001001101011100101
      = 01100100011011011111010010111001
    
    전체 계산은 63차례 더 진행되었고 변수 a-h를 수정했다.우리는 수동으로 조작할 수 없지만, 우리는 앤더에게
    h0 = 6A09E667 = 01101010000010011110011001100111
    h1 = BB67AE85 = 10111011011001111010111010000101
    h2 = 3C6EF372 = 00111100011011101111001101110010
    h3 = A54FF53A = 10100101010011111111010100111010
    h4 = 510E527F = 01010001000011100101001001111111
    h5 = 9B05688C = 10011011000001010110100010001100
    h6 = 1F83D9AB = 00011111100000111101100110101011
    h7 = 5BE0CD19 = 01011011111000001100110100011001
    
    a = 4F434152 = 001001111010000110100000101010010
    b = D7E58F83 = 011010111111001011000111110000011
    c = 68BF5F65 = 001101000101111110101111101100101
    d = 352DB6C0 = 000110101001011011011011011000000
    e = 73769D64 = 001110011011101101001110101100100
    f = DF4E1862 = 011011111010011100001100001100010
    g = 71051E01 = 001110001000001010001111000000001
    h = 870F00D0 = 010000111000011110000000011010000
    

    7단계 – 최종 값 수정


    압축 순환 후에도 블록 순환에서 우리는 각자의 변수 a-h를 해시 값에 추가함으로써 해시 값을 수정합니다. 여느 때와 마찬가지로 모든 것addition is modulo 2^32.
    h0 = h0 + a = 10111001010011010010011110111001
    h1 = h1 + b = 10010011010011010011111000001000
    h2 = h2 + c = 10100101001011100101001011010111
    h3 = h3 + d = 11011010011111011010101111111010
    h4 = h4 + e = 11000100100001001110111111100011
    h5 = h5 + f = 01111010010100111000000011101110
    h6 = h6 + g = 10010000100010001111011110101100
    h7 = h7 + h = 11100010111011111100110111101001
    

    8단계 – 최종 해시 연결


    마지막이지만 가장 중요하지 않은 점은 아니다. 그들을 모두 때려라!
    digest = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
           = B94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9
    
    완성!우리는 이미 SHA-256의 모든 단계를 상세하게 이해했다(일부 교체 포함)🙂

    위조 코드


    만약 우리가 방금 위조 코드 형식으로 완성한 모든 절차를 보고 싶다면, WikiPedia부터 시작하십시오.
    Note 1: All variables are 32 bit unsigned integers and addition is calculated modulo 232
    Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 ≤ i ≤ 63
    Note 3: The compression function uses 8 working variables, a through h
    Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
        and when parsing message block data from bytes to words, for example,
        the first word of the input message "abc" after padding is 0x61626380
    
    Initialize hash values:
    (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
    h0 := 0x6a09e667
    h1 := 0xbb67ae85
    h2 := 0x3c6ef372
    h3 := 0xa54ff53a
    h4 := 0x510e527f
    h5 := 0x9b05688c
    h6 := 0x1f83d9ab
    h7 := 0x5be0cd19
    
    Initialize array of round constants:
    (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
    k[0..63] :=
       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
       0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
       0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
       0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
       0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
       0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
    
    Pre-processing (Padding):
    begin with the original message of length L bits
    append a single '1' bit
    append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512
    append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits
    
    Process the message in successive 512-bit chunks:
    break message into 512-bit chunks
    for each chunk
        create a 64-entry message schedule array w[0..63] of 32-bit words
        (The initial values in w[0..63] don't matter, so many implementations zero them here)
        copy chunk into first 16 words w[0..15] of the message schedule array
    
        Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
        for i from 16 to 63
            s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
            s1 := (w[i- 2] rightrotate 17) xor (w[i- 2] rightrotate 19) xor (w[i- 2] rightshift 10)
            w[i] := w[i-16] + s0 + w[i-7] + s1
    
        Initialize working variables to current hash value:
        a := h0
        b := h1
        c := h2
        d := h3
        e := h4
        f := h5
        g := h6
        h := h7
    
        Compression function main loop:
        for i from 0 to 63
            S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
            ch := (e and f) xor ((not e) and g)
            temp1 := h + S1 + ch + k[i] + w[i]
            S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
            maj := (a and b) xor (a and c) xor (b and c)
            temp2 := S0 + maj
    
            h := g
            g := f
            f := e
            e := d + temp1
            d := c
            c := b
            b := a
            a := temp1 + temp2
    
        Add the compressed chunk to the current hash value:
        h0 := h0 + a
        h1 := h1 + b
        h2 := h2 + c
        h3 := h3 + d
        h4 := h4 + e
        h5 := h5 + f
        h6 := h6 + g
        h7 := h7 + h
    
    Produce the final hash value (big-endian):
    digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
    

    읽어주셔서 감사합니다.


    질문이나 의견이 있으면 트위터에서 팔로우하세요
    Qvault Classroom에서 유사한 게임의 인코딩 과정을 배우다
    Subscribe 우리의 시사 통신을 읽고 더 많은 교육 문장을 이해하다
    게시물How SHA-2 Works Step-By-Step (SHA-256)이 먼저 Qvault에 올라왔다.

    좋은 웹페이지 즐겨찾기