diff --git a/elas.py b/elas.py index 8634ffc..e9b8730 100644 --- a/elas.py +++ b/elas.py @@ -1,6 +1,8 @@ from dataclasses import dataclass from random import randint - +from random import randrange +import hashlib +import base64 @dataclass class PrimeGaloisField: @@ -118,7 +120,7 @@ class Point: return self.__class__( x=x3.value, y=y3.value, - curve=secp256k1 + curve=self.curve ) if self == other and self.y == inf: @@ -134,7 +136,7 @@ class Point: return self.__class__( x=x3.value, y=y3.value, - curve=secp256k1 + curve=self.curve ) def __rmul__(self, scalar: int) -> "Point": @@ -158,10 +160,8 @@ class Signature: s_inv = pow(self.s, -1, N) u = (z * s_inv) % N v = (self.r * s_inv) % N - return (u*G + v*pub_key).x.value == self.r - @dataclass class PrivateKey: secret: int @@ -176,34 +176,122 @@ class PrivateKey: return Signature(r, s) +def sha256(msg: str): + hash = int('0x'+hashlib.sha256(msg.encode()).hexdigest(), 16) + return hash + +def sha1(msg: str): + hash = int('0x'+hashlib.sha1(msg.encode()).hexdigest(), 16) + return hash + +def lsh(msg: str): + from lsh import LSHDigest + lsh = LSHDigest.getInstance(256, 256) + lsh.update(msg.encode()) + hash = lsh.final() + return hex(int.from_bytes(hash,'big')) + +def largePrime(bit): + def rand(n): + return randrange(2**(n-1)+1, 2**n-1) + + def gLLP(n): + while True: + + # Obtain a random number + prime_candidate = rand(n) + + for divisor in first_primes_list: + if prime_candidate % divisor == 0 and divisor**2 <= prime_candidate: + break + # If no divisor found, return value + else: return prime_candidate + + def iMRP(miller_rabin_candidate): + maxDivisionsByTwo = 0 + evenComponent = miller_rabin_candidate-1 + + while evenComponent % 2 == 0: + evenComponent >>= 1 + maxDivisionsByTwo += 1 + assert(2**maxDivisionsByTwo * evenComponent == miller_rabin_candidate-1) + + def trialComposite(round_tester): + if pow(round_tester, evenComponent, miller_rabin_candidate) == 1: + return False + for i in range(maxDivisionsByTwo): + if pow(round_tester, 2**i * evenComponent, miller_rabin_candidate) == miller_rabin_candidate-1: + return False + return True + + # Set number of trials here + numberOfRabinTrials = 20 + for i in range(numberOfRabinTrials): + round_tester = randrange(2, miller_rabin_candidate) + if trialComposite(round_tester): + return False + return True + + first_primes_list = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, + 71, 73, 79, 83, 89, 97, 101, 103, + 107, 109, 113, 127, 131, 137, 139, + 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, + 263, 269, 271, 277, 281, 283, 293, + 307, 311, 313, 317, 331, 337, 347, 349] + + while True: + n = bit + prime_candidate = gLLP(n) + if not iMRP(prime_candidate): + continue + else: + return prime_candidate + break + +def b64e(data: int): + base64_bytes = base64.b64encode(bytes.fromhex(str(data).replace('0x',''))) + base64_message = base64_bytes.decode('ascii') + return base64_message if __name__ == "__main__": - P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F - A = 0 - B = 7 - - field = PrimeGaloisField(prime=P) - secp256k1 = EllipticCurve(a=A, b=B, field=field) - - G = Point( - x=0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, - y=0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8, - curve=secp256k1) - - N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - - I = Point(x=None, y=None, curve=secp256k1) + ######[ SEC-P256-r1 ]##################################################### + P = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF + A = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC + B = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B + N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 inf = float("inf") - priv: int = 0xea11d6ada978a0b491aa5cbbe4df17a65c2fecc24448e95d1ccd854b43991bec - e = PrivateKey(priv) + field = PrimeGaloisField(prime=P) + secp256r1 = EllipticCurve(a=A, b=B, field=field) - pub = e.secret * G - print(pub) - z = 0x7e240de74fb1ed08fa08d38063f6a6a91462a815 + G = Point( + x=0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296, + y=0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5, + curve=secp256r1) + I = Point(x=None, y=None, curve=secp256r1) + + ##################################################################### + + priv = 0x9f07090a27c7f3eaf51980059cae33420865890c72d51a8d3a20fee02c82afc63ab79c604ec6b691b94bc288b910327cd38cce7f11b61ab330b9b506c149722f + #largePrime(512) + msg = '' - signature: Signature = e.sign(z) - print(e.sign(z)) - assert signature.verify(z, pub) \ No newline at end of file + z = sha256(msg) + + e = PrivateKey(priv) + pub = e.secret * G + + signature = e.sign(z) + # print(signature.verify(z, pub)) + + f_pubKey = hex(int(f'0x40{str(pub.x).replace("0x","")}{str(pub.y).replace("0x","")}',16)) + f_privKey = hex(priv) + f_msg = hex(z) + f_Sign = hex(int(f'0x30450220{str(hex(e.sign(z).r)).replace("0x","")}022100{str(hex(e.sign(z).s)).replace("0x","")}',16)) + + print(b64e(f_pubKey)) \ No newline at end of file diff --git a/lsh/__init__.py b/lsh/__init__.py new file mode 100644 index 0000000..8969bed --- /dev/null +++ b/lsh/__init__.py @@ -0,0 +1,30 @@ +#-*- coding: utf-8 -*- + +''' + Copyright (c) 2016 NSR (National Security Research Institute) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +''' + +__all__ = ['lsh_digest', 'lsh256', 'lsh512', 'hmac_lsh'] + +from .lsh_digest import LSHDigest +from .lsh256 import LSH256 +from .lsh512 import LSH512 +from .hmac_lsh import HmacLSH diff --git a/lsh/__pycache__/__init__.cpython-39.pyc b/lsh/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..fc5c5fc Binary files /dev/null and b/lsh/__pycache__/__init__.cpython-39.pyc differ diff --git a/lsh/__pycache__/hmac_lsh.cpython-39.pyc b/lsh/__pycache__/hmac_lsh.cpython-39.pyc new file mode 100644 index 0000000..69e38ef Binary files /dev/null and b/lsh/__pycache__/hmac_lsh.cpython-39.pyc differ diff --git a/lsh/__pycache__/lsh256.cpython-39.pyc b/lsh/__pycache__/lsh256.cpython-39.pyc new file mode 100644 index 0000000..1097384 Binary files /dev/null and b/lsh/__pycache__/lsh256.cpython-39.pyc differ diff --git a/lsh/__pycache__/lsh512.cpython-39.pyc b/lsh/__pycache__/lsh512.cpython-39.pyc new file mode 100644 index 0000000..229a240 Binary files /dev/null and b/lsh/__pycache__/lsh512.cpython-39.pyc differ diff --git a/lsh/__pycache__/lsh_digest.cpython-39.pyc b/lsh/__pycache__/lsh_digest.cpython-39.pyc new file mode 100644 index 0000000..1f8cf58 Binary files /dev/null and b/lsh/__pycache__/lsh_digest.cpython-39.pyc differ diff --git a/lsh/__pycache__/lsh_template.cpython-39.pyc b/lsh/__pycache__/lsh_template.cpython-39.pyc new file mode 100644 index 0000000..f3f08ea Binary files /dev/null and b/lsh/__pycache__/lsh_template.cpython-39.pyc differ diff --git a/lsh/hmac_lsh.py b/lsh/hmac_lsh.py new file mode 100644 index 0000000..984ef65 --- /dev/null +++ b/lsh/hmac_lsh.py @@ -0,0 +1,115 @@ +#-*- coding: utf-8 -*- + +''' + Copyright (c) 2016 NSR (National Security Research Institute) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +''' + +from .lsh_digest import LSHDigest + +## HMAC 구현 클래스 +class HmacLSH: + + __IPAD = 0x36 + __OPAD = 0x5c + + #__md = None + __blocksize = 0 + __i_key_pad = None + __o_key_pad = None + __outlenbits = 0 + + + ## 생성자 + # @param [in] self 객체 포인터 + # @param [in] wordlenbits 워드 길이 256, 512 중 하나여야 함 + # @param [in] outlenbits 출력 해시 길이 1 ~ wordlenbits 사이의 값이어야 함 + def __init__(self, wordlenbits, outlenbits = 0): + self.__outlenbits = outlenbits + if outlenbits > 0: + self.__md = LSHDigest.getInstance(wordlenbits, outlenbits) + else: + self.__md = LSHDigest.getInstance(wordlenbits) + self.__blocksize = self.__md.get_blocksize() + + ## HMAC 계산을 위한 초기화 + # @param [in] self 객체 포인터 + # @param [in] key 키 + def init(self, key): + + if key is None: + key = bytearray([0] * self._blocksize) + + if len(key) > self.__blocksize: + self.__md.reset() + key = self.__md.final(key) + + self.__i_key_pad = [HmacLSH.__IPAD] * self.__blocksize + self.__o_key_pad = [HmacLSH.__OPAD] * self.__blocksize + + for idx in range(len(key)): + self.__i_key_pad[idx] ^= key[idx] + self.__o_key_pad[idx] ^= key[idx] + + self.reset() + + + ## 새로운 HMAC을 계산할 수 있도록 객체를 초기화한다 + # @param [in] self 객체 포인터 + def reset(self): + self.__md.reset() + self.__md.update(self.__i_key_pad) + + + ## HMAC을 계산할 메시지를 추가한다. + # @param [in] self 객체 포인터 + # @param [in] msg 입력 메시지 + def update(self, msg): + if msg is None: + return + self.__md.update(msg) + + + ## HMAC을 계산하고 결과를 리턴한다. + # @param [in] self 객체 포인터 + # @return 계산된 HMAC 값 + def final(self): + result = self.__md.final() + self.__md.update(self.__o_key_pad) + self.__md.update(result) + result = self.__md.final() + self.reset() + return result + + ## digest 함수 - 최종 해쉬값을 계산하여 리턴한다. + # @param [in] wordlenbits 워드 길이 256, 512 중 하나여야 함 + # @param [in] outlenbits 출력 해시 길이 1 ~ wordlenbits 사이의 값이어야 함 + # @param [in] key HMAC key + # @param [in] data 입력 데이터 + # @param [in] offset 데이터 시작 오프셋 (바이트) + # @param [in] length 데이터 길이 (비트) + # @return 계산된 HMAC값 + @staticmethod + def digest(wordlenbits, outlenbits = None, key = None, data = None, offset = 0, length = -1): + hmac = HmacLSH(wordlenbits, outlenbits) + hmac.init(key) + hmac.update(data, offset, length) + return hmac.final() + diff --git a/lsh/lsh256.py b/lsh/lsh256.py new file mode 100644 index 0000000..2b4c58a --- /dev/null +++ b/lsh/lsh256.py @@ -0,0 +1,139 @@ +#-*- coding: utf-8 -*- + +''' + Copyright (c) 2016 NSR (National Security Research Institute) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +''' + +from .lsh_template import LSHTemplate + +MASK_U32 = 0xffffffff + +## LSH256 구현 클래스 +class LSH256(LSHTemplate): + + _MASK = MASK_U32 + _BLOCKSIZE = 128 + _NUMSTEP = 26 + _FORMAT_IN = ' 256: + raise ValueError("outlenbits should be 0 ~ 256") + + self._outlenbits = outlenbits + if self._outlenbits == 224: + self._cv = self.__IV224[:] + elif self._outlenbits == 256: + self._cv = self.__IV256[:] + else: + generate_iv() + + + ## 32비트 회전 연산 + # @param [in] value 회전하고자 하는 값 + # @param [in] rot 회전량 (비트) + @staticmethod + def __rol32(value, rot): + return ((value << rot) | (value >> (32 - rot))) & MASK_U32 + + + ## 스텝 함수 + # @param [in] idx 스텝 인덱스 + # @param [in] alpha 회전값 알파 + # @param [in] beta 회전값 베타 + def _step(self, idx, alpha, beta): + vl = 0 + vr = 0 + for colidx in range(8): + vl = (self._cv[colidx ] ^ self._msg[16 * idx + colidx ]) & MASK_U32 + vr = (self._cv[colidx + 8] ^ self._msg[16 * idx + colidx + 8]) & MASK_U32 + vl = LSH256.__rol32((vl + vr) & MASK_U32, alpha) ^ self._STEP[8 * idx + colidx] + vr = LSH256.__rol32((vl + vr) & MASK_U32, beta) + self._tcv[colidx ] = (vl + vr) & MASK_U32 + self._tcv[colidx + 8] = LSH256.__rol32(vr, self._GAMMA[colidx]) + + self._word_permutation() + diff --git a/lsh/lsh512.py b/lsh/lsh512.py new file mode 100644 index 0000000..cc52361 --- /dev/null +++ b/lsh/lsh512.py @@ -0,0 +1,194 @@ +#-*- coding: utf-8 -*- + +''' + Copyright (c) 2016 NSR (National Security Research Institute) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +''' + +from .lsh_template import LSHTemplate + +## 64비트 마스크 +MASK_U64 = 0xffffffffffffffff + +## LSH512 구현 클래스 +class LSH512(LSHTemplate): + + _MASK = MASK_U64 + _BLOCKSIZE = 256 + _NUMSTEP = 28 + _FORMAT_IN = ' 512: + raise ValueError("outlenbits should be 0 ~ 512") + + self._outlenbits = outlenbits + if self._outlenbits == 224: + self._cv = self.__IV224[:] + elif self._outlenbits == 256: + self._cv = self.__IV256[:] + elif self._outlenbits == 384: + self._cv = self.__IV384[:] + elif self._outlenbits == 512: + self._cv = self.__IV512[:] + else: + generate_iv() + + ## 64비트 회전 연산 + # @param [in] value 회전하고자 하는 값 + # @param [in] rot 회전량 (비트) + @staticmethod + def __rol64(value, rot): + return ((value << rot) | (value >> (64 - rot))) & MASK_U64 + + + ## 스텝 함수 + # @param [in] idx 스텝 인덱스 + # @param [in] alpha 회전값 알파 + # @param [in] beta 회전값 베타 + def _step(self, idx, alpha, beta): + vl = 0 + vr = 0 + for colidx in range(8): + vl = (self._cv[colidx ] ^ self._msg[16 * idx + colidx ]) & MASK_U64 + vr = (self._cv[colidx + 8] ^ self._msg[16 * idx + colidx + 8]) & MASK_U64 + vl = LSH512.__rol64((vl + vr) & MASK_U64, alpha) ^ self._STEP[8 * idx + colidx] + vr = LSH512.__rol64((vl + vr) & MASK_U64, beta) + self._tcv[colidx ] = (vl + vr) & MASK_U64 + self._tcv[colidx + 8] = LSH512.__rol64(vr, self._GAMMA[colidx]) + + self._word_permutation() + + diff --git a/lsh/lsh_digest.py b/lsh/lsh_digest.py new file mode 100644 index 0000000..6a98e59 --- /dev/null +++ b/lsh/lsh_digest.py @@ -0,0 +1,63 @@ +#-*- coding: utf-8 -*- + +''' + Copyright (c) 2016 NSR (National Security Research Institute) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +''' + +from .lsh256 import LSH256 +from .lsh512 import LSH512 + +## 해쉬 함수 wrapper 클래스 +class LSHDigest: + + ## 파라미터에 맞는 LSH 알고리즘 객체 생성 + # @param [in] wordlenbits 워드 길이 (비트) 256, 512만 가능함 + # @param [in] outlenbits 출력 길이 (비트) 1 ~ 256 (LSH-256) 혹은 1 ~ 512 (LSH-512) 가 가능함 + # @return LSH 객체 + @staticmethod + def getInstance(wordlenbits, outlenbits = None): + if outlenbits is None: + outlenbits = wordlenbits + + if wordlenbits == 256: + return LSH256(outlenbits) + + elif wordlenbits == 512: + return LSH512(outlenbits) + + else: + raise ValueError("Unsupported algorithm parameter"); + + + ## digest 함수 - 최종 해쉬값을 계산하여 리턴한다. + # @param [in] wordlenbits 워드 길이 256, 512 중 하나여야 함 + # @param [in] outlenbits 출력 해시 길이 1 ~ wordlenbits 사이의 값이어야 함 + # @param [in] data 입력 데이터 + # @param [in] offset 데이터 시작 오프셋 (바이트) + # @param [in] length 데이터 길이 (비트) + # @return 계산된 해쉬값 + @staticmethod + def digest(wordlenbits, outlenbits = None, data = None, offset = 0, length = -1): + if outlenbits is None: + outlenbits = wordlenbits + + lsh = LSHDigest.getInstance(wordlenbits, outlenbits) + return lsh.final(data, offset, length) \ No newline at end of file diff --git a/lsh/lsh_template.py b/lsh/lsh_template.py new file mode 100644 index 0000000..6aef012 --- /dev/null +++ b/lsh/lsh_template.py @@ -0,0 +1,240 @@ +#-*- coding: utf-8 -*- + +''' + Copyright (c) 2016 NSR (National Security Research Institute) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +''' + +import struct + +## LSH 추상 클래스 +class LSHTemplate: + + _MASK = None + _WORDBITLEN = None + _NUMSTEP = None + _BLOCKSIZE = 0 + _FORMAT_IN = None + _FORMAT_OUT = None + + _outlenbits = 0 + _boff = None + _cv = None + _tcv = None + _msg = None + _buf = None + + _STEP = None + _ALPHA_EVEN = None + _ALPHA_ODD = None + _BETA_EVEN = None + _BETA_ODD = None + _GAMMA = None + + ## 생성자 + # @param [in] self 객체 포인터 + # @param [in] outlenbits 출력 길이 (비트) + def __init__(self, outlenbits): + self._init(outlenbits) + + + ## HMAC 계산에 사용하기 위해서 내부 블록 길이 리턴 + # @param [in] self 객체 포인터 + # @return 내부 블록 길이 + def get_blocksize(self): + return self._BLOCKSIZE + + + ## 메시지 확장 함수 + # @param [in] self 객체 포인터 + # @param [in] data 입력 데이터 + # @param [in] offset 데이터 시작 인덱스 + def _msg_expansion(self, data, offset): + block = bytearray(data[offset:offset + self._BLOCKSIZE]) + self._msg[0:32] = struct.unpack(self._FORMAT_IN, block[0:self._BLOCKSIZE]) + + for i in range(2, self._NUMSTEP + 1): + idx = 16 * i + self._msg[idx ] = (self._msg[idx - 16] + self._msg[idx - 29]) & self._MASK + self._msg[idx + 1] = (self._msg[idx - 15] + self._msg[idx - 30]) & self._MASK + self._msg[idx + 2] = (self._msg[idx - 14] + self._msg[idx - 32]) & self._MASK + self._msg[idx + 3] = (self._msg[idx - 13] + self._msg[idx - 31]) & self._MASK + self._msg[idx + 4] = (self._msg[idx - 12] + self._msg[idx - 25]) & self._MASK + self._msg[idx + 5] = (self._msg[idx - 11] + self._msg[idx - 28]) & self._MASK + self._msg[idx + 6] = (self._msg[idx - 10] + self._msg[idx - 27]) & self._MASK + self._msg[idx + 7] = (self._msg[idx - 9] + self._msg[idx - 26]) & self._MASK + self._msg[idx + 8] = (self._msg[idx - 8] + self._msg[idx - 21]) & self._MASK + self._msg[idx + 9] = (self._msg[idx - 7] + self._msg[idx - 22]) & self._MASK + self._msg[idx + 10] = (self._msg[idx - 6] + self._msg[idx - 24]) & self._MASK + self._msg[idx + 11] = (self._msg[idx - 5] + self._msg[idx - 23]) & self._MASK + self._msg[idx + 12] = (self._msg[idx - 4] + self._msg[idx - 17]) & self._MASK + self._msg[idx + 13] = (self._msg[idx - 3] + self._msg[idx - 20]) & self._MASK + self._msg[idx + 14] = (self._msg[idx - 2] + self._msg[idx - 19]) & self._MASK + self._msg[idx + 15] = (self._msg[idx - 1] + self._msg[idx - 18]) & self._MASK + + ## 워드 단위 순환 함수 + # @param [in] self 객체 포인터 + def _word_permutation(self): + self._cv[ 0] = self._tcv[ 6] + self._cv[ 1] = self._tcv[ 4] + self._cv[ 2] = self._tcv[ 5] + self._cv[ 3] = self._tcv[ 7] + self._cv[ 4] = self._tcv[12] + self._cv[ 5] = self._tcv[15] + self._cv[ 6] = self._tcv[14] + self._cv[ 7] = self._tcv[13] + self._cv[ 8] = self._tcv[ 2] + self._cv[ 9] = self._tcv[ 0] + self._cv[10] = self._tcv[ 1] + self._cv[11] = self._tcv[ 3] + self._cv[12] = self._tcv[ 8] + self._cv[13] = self._tcv[11] + self._cv[14] = self._tcv[10] + self._cv[15] = self._tcv[ 9] + + ## 스텝 함수 - LSH를 상속받는 클래스에서 별도로 구현해야 함 + # @param [in] self 객체 포인터 + # @param [in] idx 스텝 인덱스 + # @param [in] alpha 회전값 알파 + # @param [in] beta 회전값 베타 + def _step(self, idx, alpha, beta): + raise NotImplementedError("Implement this method") + + ## 압축 함수 + # @param [in] self 객체 포인터 + # @param [in] data 입력 데이터 + # @param [in] offset 데이터 시작 인덱스 + def _compress(self, data, offset = 0): + + self._msg_expansion(data, offset) + + for idx in range(int(self._NUMSTEP / 2)): + self._step(2 * idx, self._ALPHA_EVEN, self._BETA_EVEN) + self._step(2 * idx + 1, self._ALPHA_ODD, self._BETA_ODD) + + for idx in range(16): + self._cv[idx] ^= self._msg[16 * self._NUMSTEP + idx] + + + ## IV 생성 함수 - LSH를 상속받는 클래스에서 별도로 구현해야 함 + # @param [in] self 객체 포인터 + # @param [in] outlenbits 출력 길이 (비트) + def _init_iv(self, outlenbits): + raise NotImplementedError("Implement this method") + + def _init(self, outlenbits): + self._boff = 0 + self._tcv = [0] * 16 + self._msg = [0] * (16 * (self._NUMSTEP + 1)) + self._buf = [0] * self._BLOCKSIZE + self._init_iv(outlenbits) + + ## 리셋 함수 - 키 입력 직후의 상태로 되돌린다 + # @param self 객체 포인터 + def reset(self): + self._init(self._outlenbits) + + + ## 업데이트 함수 + # @param [in] self 객체 포인터 + # @param [in] data 입력 데이터 + # @param [in] offset 데이터 시작 오프셋 (바이트) + # @param [in] length 데이터 길이 (비트) + def update(self, data, offset = 0, length = -1): + if data is None or len(data) == 0 or length == 0: + return + + if length == -1: + length = (len(data) - offset) << 3 + + len_bytes = length >> 3 + len_bits = length & 0x7 + + buf_idx = self._boff >> 3 + + if (self._boff & 0x7) > 0: + raise AssertionError("bit level update is not allowed") + + gap = self._BLOCKSIZE - (self._boff >> 3) + + if len_bytes >= gap: + self._buf[buf_idx:self._BLOCKSIZE] = data[offset:offset + gap] + self._compress(self._buf) + self._boff = 0 + offset += gap + len_bytes -= gap + + while len_bytes >= self._BLOCKSIZE: + self._compress(data, offset) + offset += self._BLOCKSIZE + len_bytes -= self._BLOCKSIZE + + if len_bytes > 0: + buf_idx = self._boff >> 3 + self._buf[buf_idx:buf_idx + len_bytes] = data[offset:offset + len_bytes] + self._boff += len_bytes << 3 + offset += len_bytes + + if len_bits > 0: + buf_idx = self._boff >> 3 + self._buf[buf_idx] = data[offset] & ((0xff >> len_bits) ^ 0xff) + self._boff += len_bits + + ## 종료 함수 - 최종 해쉬 값을 계산하여 리턴한다 + # @param [in] self 객체 포인터 + # @param [in] data 입력 데이터 + # @param [in] offset 데이터 시작 오프셋 (바이트) + # @param [in] length 데이터 길이 (비트) + # @return 계산된 해쉬값 + def final(self, data = None, offset = 0, length = -1): + if data is not None: + self.update(data, offset, length) + + rbytes = self._boff >> 3 + rbits = self._boff & 0x7 + + if rbits > 0: + self._buf[rbytes] |= (0x1 << (7 - rbits)) + else: + self._buf[rbytes] = 0x80 + + pos = rbytes + 1 + if (pos < self._BLOCKSIZE): + self._buf[pos:] = [0] * (self._BLOCKSIZE - pos) + + self._compress(self._buf) + + temp = [0] * 8 + for idx in range(8): + temp[idx] = (self._cv[idx] ^ self._cv[idx + 8]) & self._MASK + + self._init(self._outlenbits) + + rbytes = self._outlenbits >> 3 + rbits = self._outlenbits & 0x7 + if rbits > 0: + rbytes += 1 + + result = bytearray(struct.pack(self._FORMAT_OUT, temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[7])) + result = result[0:rbytes] + if rbits > 0: + result[rbytes - 1] &= (0xff << (8 - rbits)) + + return result diff --git a/main.py b/main.py new file mode 100644 index 0000000..e69de29 diff --git a/main.spc b/main.spc new file mode 100644 index 0000000..d18b9c4 --- /dev/null +++ b/main.spc @@ -0,0 +1,2 @@ +PUSH 1 +SHOW \ No newline at end of file diff --git a/stackp.cpp b/stackp.cpp new file mode 100644 index 0000000..df32d6e --- /dev/null +++ b/stackp.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include + +using namespace std; + +void printStack(stack Stack){ + stack tmp; + while(!Stack.empty()){ + tmp.push(Stack.top()); + cout << Stack.top() << ' '; + Stack.pop(); + } + while(!tmp.empty()){ + Stack.push(tmp.top()); + tmp.pop(); + } + cout << endl; +} + +int main(int argc, char** argv ){ + if(argc<2){ + cout << "Argument Error"; + return(0); + } + FILE* fp = fopen(argv[1],"rt"); + if(fp == NULL){ + cout << "File Error."; + return(1); + } + char str[64]; + char* stok; + int op = 0; + int arg = 0; + int loop = 0; + + stack S; + int tmp1, tmp2; + + while(!feof(fp)){ + loop++; + fgets(str, 64, fp); + stok = strtok(str,"\n"); + stok = strtok(str," "); + + op = 0; + arg = 0; + if(!strcmp(stok,"PUSH")) op = 1; + else if(!strcmp(stok,"POP")) op = 2; + else if(!strcmp(stok,"ADD")) op = 3; + else if(!strcmp(stok,"SUB")) op = 4; + else if(!strcmp(stok,"MUL")) op = 5; + else if(!strcmp(stok,"EQUAL")) op = 6; + else if(!strcmp(stok,"SHOW")) op = 7; + + if(op==1||op==2){ + stok = strtok(NULL," "); + arg = atoi(stok); + } + + switch(op){ + case 1: + S.push(arg); + break; + case 2: + S.pop(); + break; + case 3: + tmp1 = S.top(); + S.pop(); + tmp2 = S.top(); + S.pop(); + S.push(tmp1 + tmp2); + break; + case 4: + tmp1 = S.top(); + S.pop(); + tmp2 = S.top(); + S.pop(); + S.push(tmp1 - tmp2); + break; + case 5: + tmp1 = S.top(); + S.pop(); + tmp2 = S.top(); + S.pop(); + S.push(tmp1 * tmp2); + break; + case 6: + tmp1 = S.top(); + S.pop(); + tmp2 = S.top(); + S.pop(); + S.push((tmp1 == tmp2)); + break; + case 7: + cout << S.top() << endl; + break; + } + + // printStack(S); + } +} \ No newline at end of file diff --git a/stackp.exe b/stackp.exe new file mode 100644 index 0000000..e01e1e4 Binary files /dev/null and b/stackp.exe differ