CTF密码学Crypto超详细总结!

CTF---密码学(1)--古典密码-理论与实战详解 总的来说,密码学一般分为古典密码学和现代密码学: 古代密码学没有清晰的定义,依赖于密码创作者的想象力。通常包括单表替换加密,多表替换加密和其他的加密方法。 现代密码学起源于20世纪中后期。主要包含:对称加密(DES,AES,RC4);非对称加密(RSA,ElGamal,椭圆曲线加密);哈希函数(MD5,SHA-1,SHA-512);数字签名(RSA签名,ElGamal签名,DSA签名) 阅读详情

目录

(一)古典密码

1.摩斯密码

2.移位密码

(1)凯撒密码

(2)栅栏密码

①常规型

②W型

(3)曲路密码

(4)列移位

(5)rot13

3.替换密码

(1)行置换密码

(2)棋盘密码

(3)vigenere维吉尼亚密码

(4)培根密码

(5)猪圈密码

(6)键盘密码

①电脑键盘

②键盘围成的密码

(7)盲文密码

(8)幂数加密/云影密码

(9)brainfuck

(10)Ook

(11)标准银河字母

(12)简单替换密码

(二)编码

1.ASCII编码

2.Base编码

3.unicode编码

4.url编码

5.html编码

(1)普通html编码

(2)html实体编码

6.rabbit编码

7.python反编译

8.quipquip词频分析

(三)现代密码学–对称加密

1.DES

2.AES

3.RC4

(四)现代密码学–非对称加密

1.RSA

(1)基础已知p、q、e求d

(2)知道加密后的文本和公钥文本(就是知道了n、p、q、e、c求m)

(3)知道加密后的文本和私钥文本

(4)RSA共模攻击

(5)分解素数多于两个

(6)n分解出来就一个(即n是质数)

2.DH

3.ECC

(1)椭圆曲线加密基础

(2)椭圆曲线数字签名

4.DSA

5.ElGamal

(五)国密

(六)用提取、删除、替换字符

(七)01或者AB这种相反面

(八)Linux系统的 shadow 文件格式

(九)MD5


(一)古典密码
1.摩斯密码

有时候一串101010可能代表的是-.-.-.

img

2.移位密码
(1)凯撒密码

密码统一移动几位

(2)栅栏密码
①常规型

栅栏密码是一种相对简单但又具有一定保密性的加密方法。它的原理是将明文按照一定的行数写成栅栏状,然后按列读取得到密文。例如,明文“HELLO WORLD”设定行数为2,写成栅栏状为:

H L O R E L W D

按列读取得到密文“HLOR ELWD

②W型

img

(3)曲路密码

(4)列移位

举例: 明文:The quick brown fox jumps over the lazy dog 密钥:how are u

密文:qoury inpho Tkool hbxva uwmtd cfseg erjez

(5)rot13

就是凯撒密码偏移量为13的情况

3.替换密码
(1)行置换密码

加密

解密

(2)棋盘密码

img

明文 HELLO,加密后就是 23 15 31 31 34

(3)vigenere维吉尼亚密码

(4)培根密码

(5)猪圈密码

img

(6)键盘密码
①电脑键盘

例如:11为Q,23为D

②键盘围成的密码

例如:xrv为c

(7)盲文密码

(8)幂数加密/云影密码

(9)brainfuck
++++++++++\[>+++++++>++++++++++>+++>+<<<<-\]
++.>+.+++++++…+++.>++.<<+++++++++++++++.
.+++.------.--------.>+.>.


(10)Ook
#-\*-coding:utf-8-\*-
import sys
from collections import deque
​
class LoopError(Exception):
    pass
​
class OokParser(object):
    def \_\_init\_\_(self):
        self.BEGIN = ('!', '?')
        self.END = ('?', '!')
        self.primitives = {('.', '.'): 'inc',
                           ('!', '!'): 'dec',
                           ('.', '?'): 'right',
                           ('?', '.'): 'left',
                           ('!', '.'): 'write',
                           ('.', '!'): 'read'}
                           
    def parse(self, input\_text):
        items = input\_text.lower().replace('ook','').replace(' ', '').replace('\\n','').replace('\\r','')
        for i in range(0, len(items), 2):
            x = (items\[i\], items\[i+1\])
            if x in self.primitives or x in (self.BEGIN, self.END):
                yield x
​
class BrainfuckParser(object):
    def \_\_init\_\_(self):
        self.BEGIN = '\['
        self.END = '\]'
        self.primitives = {'+': 'inc',
                           '-': 'dec',
                           '>': 'right',
                           '<': 'left',
                           '.': 'write',
                           ',': 'read'}
                           
    def parse(self, input\_text):
        for x in input\_text:
            if x in self.primitives or x in (self.BEGIN, self.END):
                yield x
​
class Interpreter(object):
    MAX\_NESTED\_LOOPS = 1000
​
    def \_\_init\_\_(self, ook\_mode=True):
        self.bf\_parser = BrainfuckParser()
        self.ook\_parser = OokParser()
        self.set\_parser(ook\_mode and self.ook\_parser or self.bf\_parser)
​
    def reset(self):
        self.cells = deque(\[0\])
        self.index = 0
        self.input\_buffer = \[\]
        self.output\_buffer = \[\]
        self.open\_loops = 0
        self.loop = \[\]
​
    def inc(self):
        self.cells\[self.index\] += 1
​
    def dec(self):
        self.cells\[self.index\] -= 1
​
    def right(self):
        self.index += 1
        if self.index >= len(self.cells):
            self.cells.append(0)
​
    def left(self):
        if self.index == 0:
            self.cells.appendleft(0)
        else:
            self.index -= 1
​
    def write(self):
        self.output\_buffer.append(self.cells\[self.index\])
            
    def read(self):
        try:
            self.cells\[self.index\] = int(raw\_input("Your input: "))
        except (TypeError, ValueError):
            print ("Invalid input! Continuing ...")
​
    def as\_ascii(self):
        return "".join(\[chr(c) for c in self.output\_buffer\])
​
    def set\_parser(self, parser):
        self.parser = parser
        self.reset()
​
    def interpret\_raw\_text(self, text):
        self.input\_buffer.extend(self.parser.parse(text))
        try:
            self.interpret\_items(self.input\_buffer)
        except IndexError:
            print (" ... (incomplete)")
        except LoopError:
            print ("LoopError ... exiting")
            sys.exit(1)
​
    def interpret\_items(self, items):
        for item in items:
            if self.open\_loops:
                self.interpret\_inside\_loop(item)
            else:
                self.interpret\_directly(item)
​
    def interpret\_inside\_loop(self, item):
        if item == self.parser.END:
            self.open\_loops -= 1
            if self.open\_loops == 0:
                while self.cells\[self.index\]:
                    self.interpret\_items(self.loop)
                return
        elif item == self.parser.BEGIN:
            if self.open\_loops < self.MAX\_NESTED\_LOOPS:
                self.open\_loops += 1
            else:
                raise LoopError("Nesting maximum (%s) exceeded" 
                                % self.MAX\_NESTED\_LOOPS)
        self.loop.append(item)
​
    def interpret\_directly(self, item):
        if item == self.parser.END:
            raise ValueError("End without begin")
        elif item == self.parser.BEGIN:
            self.open\_loops = 1
            self.loop = \[\]
        elif item in self.parser.primitives:
            method = self.parser.primitives\[item\]
            getattr(self, method)()
        else:
            print ("Unknown token '%s' - ignored") % (item, )
​
    def interpret\_file(self, fname):
        file = open(fname, 'r')
        self.interpret\_raw\_text(file.read())
        
    def interactive\_mode(self):
        print ("Ook! and Brainfuck interpreter V1.0")
        print ("Type '?' to display the status of the interpreter. ")
        print ("Type 'b' to enter brainfuck mode. Empty input quits.")
        while True:
            inp = raw\_input("oo> ").strip()
            if inp == "?":
                print (self)
            elif inp == "b":
                print ("Entering brainfuck mode. Type 'o' to return to Ook!")
                self.set\_parser(self.bf\_parser)
            elif inp == "o":
                print ("Entering Ook! mode. Type 'b' to return to brainfuck.")
                self.set\_parser(self.ook\_parser)
            elif inp == "":
                print (self)
                break
            else:
                self.interpret\_raw\_text(inp)
​
    def \_\_repr\_\_(self):
        rep = "\\n".join(\["Cells\\t\\t: %s", 
                         "Raw output\\t: %s",
                         "ASCII output\\t: %s"\])
​
        return rep % (list(self.cells),
                      " ".join(\[str(i) for i in self.output\_buffer\]), 
                      self.as\_ascii())
​
def print\_usage():
    print ("\\nUsage:")
    print ("\\tInterpret Ook! : python ook.py -o <FILENAME>")        
    print ("\\tInterpret BrainFuck : python ook.py -b <FILENAME>")
    print ("\\tInteractive mode: python ook.py -i\\n")
​
​
if \_\_name\_\_ == '\_\_main\_\_':
    if len(sys.argv) < 2:
        print\_usage()
    elif len(sys.argv) == 2 and sys.argv\[1\] == "-i":
        ook = Interpreter()
        ook.interactive\_mode()
    elif len(sys.argv) == 3:
        if sys.argv\[1\] == "-b":
            ook = Interpreter(ook\_mode=False)
            ook.interpret\_file(sys.argv\[2\])
            print (ook)
        elif sys.argv\[1\] == "-o":
            ook = Interpreter(ook\_mode=True)
            ook.interpret\_file(sys.argv\[2\])
            print (ook)
        else:
            print\_usage()
    else:
        print\_usage()
​


(11)标准银河字母

img

(12)简单替换密码

(二)编码
1.ASCII编码

2.Base编码

base64、32、16。。。

3.unicode编码
源文本: The
&#x \[Hex\]: The
&# \[Decimal\]: The
\\U \[Hex\]: \\U0054\\U0068\\U0065
\\U+ \[Hex\]: \\U+0054\\U+0068\\U+0065


4.url编码
例子:The quick
%54%68%65%20%71%75%69%63%6b


5.html编码
(1)普通html编码

特征:&# 开头 由 &# 开头,后面加数字

(2)html实体编码

img

6.rabbit编码

跟base64很像,但是需要密钥,Rabbit加密开头部分通常为U2FsdGVkX1

7.python反编译

EasyPythonDecompiler软件,1.pyc转1.py

8.quipquip词频分析
(三)现代密码学–对称加密
1.DES
2.AES
3.RC4

RC4包含两个算法: 1.密钥调度算法(KSA) 2.伪随机数生成算法(PRGA)

RC4是经典流密码之一,由于加密和解密使用相同的密钥,所以也是对称密码的一种。由于RC4存在弱点,现已禁止在TLS中使用RC4加解密算法。

RC4会根据明文长度将密钥扩展到与明文相同的长度,并遵从逐个字节加密的原则。加密的原理是异或。

def rc4\_init(s\_box, key, key\_len):  # rc4初始化函数,产生s\_box
    k = \[0\] \* 256
    i = j = 0
    for i in range(256):
        s\_box\[i\] = i
        k\[i\] = key\[i % key\_len\]
    for i in range(256):
        j = (j + s\_box\[i\] + ord(k\[i\])) % 256
        s\_box\[i\], s\_box\[j\] = s\_box\[j\], s\_box\[i\]
def rc4\_crypt(s\_box, data, data\_len, key, key\_len):  # rc4算法,由于异或运算的对合性,RC4加密解密使用同一套算法,加解密都是它
    rc4\_init(s\_box, key, key\_len)
    i = j = 0
    for k in range(data\_len):
        i = (i + 1) % 256
        j = (j + s\_box\[i\]) % 256
        s\_box\[i\], s\_box\[j\] = s\_box\[j\], s\_box\[i\]
        t = (s\_box\[i\] + s\_box\[j\]) % 256
        data\[k\] ^= s\_box\[t\]
 
if \_\_name\_\_ == '\_\_main\_\_':
    s\_box = \[0\] \* 257  # 定义存放s\_box数据的列表
 
    # 此处的data即要解密的密文,需要定义成列表形式,其中的元素可以是十六进制或十进制数
    # 如果题目给出的是字符串,需要你自己先把数据处理成列表形式再套用脚本
    data = \[0xB6,0x42,0xB7,0xFC,0xF0,0xA2,0x5E,0xA9,0x3D,0x29,0x36,0x1F,0x54,0x29,0x72,0xA8,0x63,0x32,0xF2,0x44,0x8B,0x85,0xEC,0xD,0xAD,0x3F,0x93,0xA3,0x92,0x74,0x81,0x65,0x69,0xEC,0xE4,0x39,0x85,0xA9,0xCA,0xAF,0xB2,0xC6\]  
    #key一定要字符串
    key = "gamelab@"
 
    rc4\_crypt(s\_box, data, len(data), key, len(key))
    for i in data:
        print(chr(i), end='')


(四)现代密码学–非对称加密
1.RSA

img

(1)基础已知p、q、e求d
#RSA---知道p、q、e求d
from Crypto.Util.number import \*
#gmpy2 是一个用于高精度数学运算的 Python 库,它提供了快速的大整数运算功能
import gmpy2
​
# 定义素数 p 和 q
p = 275127860351348928173285174381581152299
q = 319576316814478949870590164193048041239
​
# 计算模数 n
n = p \* q
​
# 计算欧拉函数 φ(n)
r = (p - 1) \* (q - 1)
​
# 选择公钥指数 e
e = 65537
​
# 计算私钥指数 d
d = gmpy2.invert(e, r)
# 打印私钥指数 d
print("私钥指数 d:", d)
​


(2)知道加密后的文本和公钥文本(就是知道了n、p、q、e、c求m)

step1:使用openssl解出e和n

openssl rsa -pubin -text -modulus -in warmup -in pubkey.pem


e=65537,n=Modulus的十六进制

step2:进制转换(16转10)

def hex\_to\_decimal(hex\_string):
    try:
        decimal\_num = int(hex\_string, 16)
        return decimal\_num
    except ValueError:
        print("输入的不是有效的十六进制字符串。")
        return None
​
​
hex\_str = "C2636AE5C3D8E43FFB97AB09028F1AAC6C0BF6CD3D70EBCA281BFFE97FBE30DD"
result = hex\_to\_decimal(hex\_str)
if result is not None:
    print(f"转换为十进制是: {result}")


n=87924348264132406875276140514499937145050893665602592992418171647042491658461

step3:使用yafu分解n,得出p、q

step4:加密后的文本flag.enc的十六进制再转为十进制就是c

c=49412914049026066227292604633959399022586841904231599586841156187258952420473

step5:根据基础ras脚本解出m

from Crypto.Util.number import \*
import gmpy2
e=65537

p= 319576316814478949870590164193048041239
q= 275127860351348928173285174381581152299
n=p\*q
c = 49412914049026066227292604633959399022586841904231599586841156187258952420473
r=(p-1)\*(q-1)
d=gmpy2.invert(e,r)
m=pow(c,d,n)
print(m)



得到m=4865677769286717240419296208145914517832094464845949055035370987525602570

step6:m转为16进制,再转为ASCII码(这样更不容易出错,有些题会出现多一个字符的情况)

def decimal\_to\_hex(decimal\_num):
    hex\_chars = "0123456789ABCDEF"
    if decimal\_num == 0:
        return '0'
    hex\_str = ''
    negative = False
    if decimal\_num < 0:
        negative = True
        decimal\_num = -decimal\_num
    while decimal\_num > 0:
        remainder = decimal\_num % 16
        hex\_str = hex\_chars\[remainder\] + hex\_str
        decimal\_num //= 16
    if negative:
        hex\_str = '-' + hex\_str
    return hex\_str


decimal\_num =4865677769286717240419296208145914517832094464845949055035370987525602570
hex\_result = decimal\_to\_hex(decimal\_num)
print(f"转换为十六进制是: {hex\_result}")
    


这种情况是多了一位,删去2

(3)知道加密后的文本和私钥文本
openssl rsautl -decrypt -in key.txt(加密后的文件) -inkey pub.key(私钥) -out flag.txt


(4)RSA共模攻击

所谓共模,就是明文m相同,模n相同,用两个公钥e1,e2加密得到两个私钥d1,d2和两个密文c1,c2 共模攻击,即当n不变的情况下,知道n,e1,e2,c1,c2 。可以在不知道d1,d2的情况下,解出m

import gmpy2
n=13060424286033164731705267935214411273739909173486948413518022752305313862238166593214772698793487761875251030423516993519714215306808677724104692474199215119387725741906071553437840256786220484582884693286140537492541093086953005486704542435188521724013251087887351409946184501295224744819621937322469140771245380081663560150133162692174498642474588168444167533621259824640599530052827878558481036155222733986179487577693360697390152370901746112653758338456083440878726007229307830037808681050302990411238666727608253452573696904083133866093791985565118032742893247076947480766837941319251901579605233916076425572961
c1=12847007370626420814721007824489512747227554004777043129889885590168327306344216253180822558098466760014640870748287016523828261890262210883613336704768182861075014368378609414255982179769686582365219477657474948548886794807999952780840981021935733984348055642003116386939014004620914273840048061796063413641936754525374790951194617245627213219302958968018227701794987747717299752986500496848787979475798026065928167197152995841747840050028417539459383280735124229789952859434480746623573241061465550303008478730140898740745999035563599134667708753457211761969806278000126462918788457707098665612496454640616155477050
c2=6830857661703156598973433617055045803277004274287300997634648800448233655756498070693597839856021431269237565020303935757530559600152306154376778437832503465744084633164767864997303080852153757211172394903940863225981142502888126928982009493972076013486758460894416710122811249903322437742241269681934551237431668187006176418124934488775505816544733929241927900392924886649420943699356314278255683484998359663404611236056664149725644051300950988495549164517140159041907329062655574220869612072289849679613024196448446224406889484578310512232665571188351621585528255501546941332782446448144033997067917984719103068519
e1=117
e2=65537
r,s1,s2 = gmpy2.gcdext(e1, e2)   
m = (pow(c1,s1,n)\*pow(c2,s2,n)) % n   
print(m)


(5)分解素数多于两个

攻防世界:baigeiRSA2

step1:分解n,素数为5个

step2:脚本

from Crypto.Util.number import \*
import gmpy2
e=65537
p=9401433281508038261
q=13716847112310466417
s=11215197893925590897
t=11855687732085186571
y=10252499084912054759
n=p\*q\*s\*t\*y

c =144009221781172353636339988896910912047726260759108847257566019412382083853598735817869933202168
r=(p-1)\*(q-1)\*(s-1)\*(t-1)\*(y-1)
d=gmpy2.invert(e,r)
m=pow(c,d,n)
print(m)


大体都一样,就是n=p_q_s_t_y,r=(p-1)(q-1)(s-1)(t-1)(y-1),这两个地方变了

(6)n分解出来就一个(即n是质数)
from Crypto.Util.number import \*
import gmpy2
e=65537

p= 2277984791022346369005533904783614818826102788659651508959767202083843778453131366658916382803461140562467908905967443285040501371560088604538394878005827646410146244954745505114406792711000349929611271710262426493710967674490536959788665890671796421985910748091011210709414415838780453626144971988788672588103654983

n=p
c = 415510106371698055042355817455792784402467839071261284227679808181073943762112386236619891503158397068812942349049185918370823556100880803528976860244812587012654626659823858350868438615582709075400040571632681052556974452098591809573228654622307014559692352778252371646024960520522510301144376842967556042367321117
r=(p-1)
d=gmpy2.invert(e,r)
m=pow(c,d,n)
print(m)


大体都一样,就是n=p,r=p-1

2.DH
3.ECC

(1)椭圆曲线加密基础

知道p(有限特征值)、a、b、G(基点)、k(私钥),求公钥K,也就是上图的C1

import collections
import random
 
EllipticCurve = collections.namedtuple('EllipticCurve', 'name p a b g n h')
 
curve = EllipticCurve(
   'secp256k1',
   # Field characteristic.
   p=int(input('p=')),
   # Curve coefficients.
   a=int(input('a=')),
   b=int(input('b=')),
   # Base point.
   g=(int(input('Gx=')),
      int(input('Gy='))),
   # Subgroup order.
   n=int(input('k=')),
   # Subgroup cofactor.
   h=1,
)
 
 
# Modular arithmetic ##########################################################
 
def inverse\_mod(k, p):
   """Returns the inverse of k modulo p.
  This function returns the only integer x such that (x \* k) % p == 1.
  k must be non-zero and p must be a prime.
  """
   if k == 0:
       raise ZeroDivisionError('division by zero')
 
   if k < 0:
       # k \*\* -1 = p - (-k) \*\* -1 (mod p)
       return p - inverse\_mod(-k, p)
 
   # Extended Euclidean algorithm.
   s, old\_s = 0, 1
   t, old\_t = 1, 0
   r, old\_r = p, k
 
   while r != 0:
       quotient = old\_r // r
       old\_r, r = r, old\_r - quotient \* r
       old\_s, s = s, old\_s - quotient \* s
       old\_t, t = t, old\_t - quotient \* t
 
   gcd, x, y = old\_r, old\_s, old\_t
 
   assert gcd == 1
   assert (k \* x) % p == 1
 
   return x % p
 
 
# Functions that work on curve points #########################################
 
def is\_on\_curve(point):
   """Returns True if the given point lies on the elliptic curve."""
   if point is None:
       # None represents the point at infinity.
       return True
 
   x, y = point
 
   return (y \* y - x \* x \* x - curve.a \* x - curve.b) % curve.p == 0
 
 
def point\_neg(point):
   """Returns -point."""
   assert is\_on\_curve(point)
 
   if point is None:
       # -0 = 0
       return None
 
   x, y = point
   result = (x, -y % curve.p)
 
   assert is\_on\_curve(result)
 
   return result
 
 
def point\_add(point1, point2):
   """Returns the result of point1 + point2 according to the group law."""
   assert is\_on\_curve(point1)
   assert is\_on\_curve(point2)
 
   if point1 is None:
       # 0 + point2 = point2
       return point2
   if point2 is None:
       # point1 + 0 = point1
       return point1
 
   x1, y1 = point1
   x2, y2 = point2
 
   if x1 == x2 and y1 != y2:
       # point1 + (-point1) = 0
       return None
 
   if x1 == x2:
       # This is the case point1 == point2.
       m = (3 \* x1 \* x1 + curve.a) \* inverse\_mod(2 \* y1, curve.p)
   else:
       # This is the case point1 != point2.
       m = (y1 - y2) \* inverse\_mod(x1 - x2, curve.p)
 
   x3 = m \* m - x1 - x2
   y3 = y1 + m \* (x3 - x1)
   result = (x3 % curve.p,
             -y3 % curve.p)
 
   assert is\_on\_curve(result)
 
   return result
 
 
def scalar\_mult(k, point):
   """Returns k \* point computed using the double and point\_add algorithm."""
   assert is\_on\_curve(point)
 
 
 
   if k < 0:
       # k \* point = -k \* (-point)
       return scalar\_mult(-k, point\_neg(point))
 
   result = None
   addend = point
 
   while k:
       if k & 1:
           # Add.
           result = point\_add(result, addend)
 
       # Double.
       addend = point\_add(addend, addend)
 
       k >>= 1
 
   assert is\_on\_curve(result)
 
   return result
 
 
# Keypair generation and ECDHE ################################################
 
def make\_keypair():
   """Generates a random private-public key pair."""
   private\_key = curve.n
   public\_key = scalar\_mult(private\_key, curve.g)
 
   return private\_key, public\_key
 
 
 
private\_key, public\_key = make\_keypair()
print("private key:", hex(private\_key))
print("public key: (0x{:x}, 0x{:x})".format(\*public\_key))



假设椭圆曲线方程为,发送方和接收方选取的私钥k=7,基点P为(0,1),假设发送方想要把一个数4发送给接收方,那么先将x=4带入曲线方程,得到明文M(4,4)。再根据k和P计算出公钥Q=7P=(42, 14),随机选一个数r=3,那么密文c= E(M)=(rP,M+rQ)=((19, 28), (6, 45))。

接收方知道了密文c和私钥k,只需要按照解密法则M=D©= M+rQ-krP就可以求出明文M(4,4)

#coding:gbk  
 
p = 53  
 
i = lambda x: pow(x, p-2, p)  
 
def add(A, B):#加法运算  
 
    (u, v), (w, x) = A, B  
 
    assert u != w or v == x  
 
    if u == w: m = (3\*u\*w + 1) \* i(v+x)  
 
    else: m = (x-v) \* i(w-u)  
 
    y = m\*m - u - w   
 
    z = m\*(u-y) - v  
 
    return y % p, z % p  
 
def opposite(A):#取A的相反数,也就是将A变成-A  
 
    return A\[0\],(-A\[1\])%p  
 
def mul(t, A, B=0):#乘法运算  
 
    if not t:  
 
        return B  
 
    if t%2==0:  
 
        return mul(t//2, add(A,A), B)  
 
    elif B!=0:  
 
        return mul(t//2, add(A,A), add(B,A))  
 
    else:  
 
        return mul(t//2, add(A,A),A)  
 
M=(4,4)  
 
P=(0,1)  
 
r=3  
 
k=7  
 
Q=mul(k,P)  
 
c=(mul(r,P),add(M,mul(r,Q)))  
 
print("公钥Q是",Q)  
 
print("密文c是",c)  
 
print("明文M是",add(c\[1\],opposite(mul(k,c\[0\])))) 


(2)椭圆曲线数字签名

椭圆曲线数字签名算法,它利用椭圆曲线密码学(ECC)对数字签名算法(DSA)进行模拟,其安全性基于椭圆曲线离散对数问题。

但是当某些数值相同时会出现一些安全问题。 分析代码可以看出,存在随机数重复使用。具体来说,这段代码中签名的过程中使用了相同的随机数 k 来对不同的消息进行签名。这种情况下,可以通过分析两个相同 k 值对应的消息签名来恢复私钥 dA。

在 ECDSA 中,每次签名过程中都会使用一个随机数 k,以确保生成唯一的签名。然而,如果相同的随机数 k 被重复使用来对不同的消息进行签名,攻击者就有可能通过数学分析和推导计算出私钥 dA。

import sympy
from hashlib import sha1
from Cryptodome.Util.number import long\_to\_bytes , bytes\_to\_long


def calculate\_private\_key(r1, s1, s2, h1, h2, n):
    # 计算k值
    k = ((h1 - h2) \* sympy.mod\_inverse(s1 - s2, n)) % n
    # 计算私钥dA
    dA = (sympy.mod\_inverse(r1, n) \* (k \* s1 - h1)) % n
    return dA



if \_\_name\_\_ == "\_\_main\_\_":
    # 定义椭圆曲线的参数
    n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
    # 签名中的r1, s1, s2值
    r1 = 4690192503304946823926998585663150874421527890534303129755098666293734606680
    s1 = 111157363347893999914897601390136910031659525525419989250638426589503279490788
    s2 = 74486305819584508240056247318325239805160339288252987178597122489325719901254
    h1 = bytes\_to\_long(sha1(b'Hi.').digest())
    h2 = bytes\_to\_long(sha1(b'hello.').digest())
    private\_key = calculate\_private\_key(r1, s1, s2, h1, h2, n)
    print(f'flag{{{private\_key}}}')



4.DSA
5.ElGamal
(五)国密
(六)用提取、删除、替换字符
grep -o '\[A-Z\]' 1.txt | tr -d '\\n' >>2.txt
sed -i -e 's/ZERO/0/g' -e 's/ONE/1/g' 2.txt


sed 's/v\[0-9\]\\+\\s\*=\\s\*//g' 1.txt | sed 's/u//g' | tr -d '\\n ' | tr ';' ',' > output.txt删除v1-v43、u、换行、替换;为,



(七)01或者AB这种相反面

带有相反面的,比如黑白这种,想到转换成二进制0101或者摩斯密码.-.-

或者培根密码

(八)Linux系统的 shadow 文件格式

特征:就是Linux的shadow文件格式。。。

工具:Kali Linux 中的 John

e.g.

root:$6$HRMJoyGA$26FIgg6CU0bGUOfqFB0Qo9AE2LRZxG8N3H.3BK8t49wGlYbkFbxVFtGOZqVIq3q
Q6k0oetDbn2aVzdhuVQ6US.:17770:0:99999:7:::


Linux的 /etc/shadow 文件存储了该系统下所有用户口令相关信息,只有 root 权限可以查看,用户口令是以 Hash + Salt 的形式保护的。 每个字段都用 “$” 或“:”符号分割; 第一个字段是用户名,如root ; 第二个字段是哈希算法,比如 6 代表SHA-512,1 代表 MD5; 第三个字段是盐,比如上面的 HRMJoyGA 第四个字段是口令+盐加密后的哈希值 后面分别是密码最后一次修改日期、密码的两次修改间隔时间(和第三个字段相比)、密码的有效期(和第三个字段相比)、密码修改到期前的警告天数(和第五个字段相比)、密码过期后的宽限天数(和第五个字段相比)、账号失效时间,这里不太重要要;

直接跑 John 试试

john shadow

如果解开了,加 --show 查看解密口令

john --show shadow

(九)MD5

特征:一般为16位或32位 ,由数字和小写字母组成

0906b080b03ea64d0534d36b2bd9edb8

黑客/网络安全学习包

资料目录

  1. 成长路线图&学习规划

  2. 配套视频教程

  3. SRC&黑客文籍

  4. 护网行动资料

  5. 黑客必读书单

  6. 面试题合集

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

1.成长路线图&学习规划

要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

2.视频教程

很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

3.SRC&黑客文籍

大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录

SRC技术文籍:

黑客资料由于是敏感资源,这里不能直接展示哦!

4.护网行动资料

其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!

5.黑客必读书单

**

**

6.面试题合集

当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。

更多内容为防止和谐,可以扫描获取~

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

本次CTF·泰山杯网络安全的基础知识部分 最近参加的网络安全大赛的CTF基础知识部分,还会继续补充 阅读详情

相关推荐

CTF密码学-加解密总结

零基础学黑客,搜索公众号:白帽子左一 密码学基本简介 密码学(在西欧语文中,源于希腊语kryptós“隐藏的”,和gráphein“书写”)是研究如何隐密地传递信息的学科。 在现代特别指对信息以及其传输的数学性研究,常被认为是数学和计算机科学的分支,和信息论也密切相关。 著名的密码学者Ron Rivest解释道:“密码学是关于如何在敌人存在的环境中通讯”,自工程学的角度,这相当于密码学与纯数学的异同。 密码学是信息安全等相关议题,如认证、访问控制的核心。密码学的首要目的是隐藏信息的涵义,并不是隐藏信息的存

hackzkaq的博客 9401

古典密码(一)

恺撒密码(Caesar cipher)又称为恺撒加密、恺撒变换、变换加密,它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。只能对字母加解密并且符号无法复制,粘贴后会直接显示明文,即使使用符号,也不会影响密码分析,亦可用在其它替代式的方法,曾经是美国内战时盟军使用的密码。摩斯密码(Morse code),又称为摩尔斯电码、摩斯电码,是一种时通时断的信号代码,这种信号代码通过不同的排列顺序来表达不同的英文字母、数字和标点符号等。26个字母的摩斯密码表。

2301_79258552的博客 5536

CTF-Crypto 出题思路与解题思路

ctf 夺旗赛解题思路 crypto密码学

Jang2023的博客 4730

CTF中常见密码学(一)

CTF中常见的密码学

御七彩虹猫 9835

CTF-Crypto密码学

由于内容过多,分两篇展示 密码学 01密码学概述 密码学的发展 密码编码学 编码与加密? 编码为一类映射的关系(一一映射) 加密为一类算法(有算法(公开的),密钥(不可泄漏)) 明文 ------> 密文 plain text cipher text 对称密码和不对称密码算法 对称密码算法优点:加密解密速度快 缺点:密钥不能泄漏(除了AES,因为密钥很长,目前无机器能够在短时间内破解) 对称密码算法常考DES 非对称密码算法(Asymetric cipher): 加密密钥和解密密钥

am_03的博客 1691

密码学--CTF Crypto 总结

密码学简介 密码学(Cryptography)一般可分为古典密码学和现代密码学。 其中,古典密码学,作为一种实用性艺术存在,其编码和破译通常依赖于设计者和敌手的创造力与技巧,并没有对密码学原件进行清晰的定义。其主要包含以下几个方面 单表替换加密 多表替换加密 奇奇怪怪的加密方式 而现代密码学则起源于 20 世纪末出现的大量相关理论,这些理论使得现代密码学成为了一种可以系统而严格地学习的科学。现代密码学又可以简单的分为以下几个方面 对称密码,以 DES,AES,RC4 为代表。 非对称密码,以

渗透测试研究中心 8456

CTF密码学Crypto超详细总结!收藏这篇就够了

(一)古典密码1.摩斯密码2.移位密码(1)凯撒密码(2)栅栏密码①常规型②W型(3)曲路密码(4)列移位(5)rot133.替换密码(1)行置换密码(2)棋盘密码(3)vigenere维吉尼亚密码(4)培根密码(5)猪圈密码(6)键盘密码①电脑键盘②键盘围成的密码(7)盲文密码(8)幂数加密/云影密码(10)Ook(11)标准银河字母(12)简单替换密码(二)编码1.ASCII编码2.Base编码3.unicode编码4.url编码。

leah126的博客 1779

Oracle19c-集群节点重新添加

Oracle RAC集群在极端情况下,如硬件、主机,集群软件损坏,导致集群节点永久无法使用,需要对集群节点进行修复,删除节点集群信息并重新加入集群,以恢复集群原有的架构。 本文主要讲述一套两节点的Oracle19c RAC集群,节点一orcl01由于主机异常无法正常启动,在对主机进行重装之后,需要将orcl01节点重新加入集群的操作步骤。环境信息: 操作系统:Linux 7 RAC集群:19C 主机节点:orcl0...

sinat_36757755的博客 2352

CTF——Crypto密码学题型总结

积累一下 CTF 中 crypto 密码类的题型。 感谢 BugKu 提供了很多加解密工具,链接:http://tool.bugku.com/ 感谢 SSL在线工具网址提供了很多工具,链接:http://www.ssleye.com/ 个人常用的 text bin hex base64 dec 转码工具:https://conv.darkbyte.ru/   1. 摩斯密码 特征:点和横的组合...

hahaha233330的博客 4万+

雷赛控制卡全方位使用指南:从硬件连接到高级应用

雷赛控制卡以其接口简单、编程便捷、性价比高的特点,成为中小自动化设备的理想选择。使用时需注意:硬件连接需注重抗干扰设计(屏蔽线、接地);软件开发需合理配置运动参数(脉冲当量、加减速);调试阶段需充分利用 DMCStudio 工具验证性能。通过本文介绍的方法,可快速实现从硬件搭建到复杂运动控制的全流程开发,满足雕刻、切割、装配等多场景的自动化需求。

品质生活,极致编程。 3773

Unipush2.0 App消息推送(在线+离线推送)

使用unipush2.0进行消息推送,包含在线跟离线

weixin_50251467的博客 3699

CTF Crypto(密码学)总结

最近接触了一些密码学的题,感觉特别有意思,写下博客来记录一下,以免忘记 一:哈夫曼树 哈夫曼树(也称为最优二叉树),虽然(目前)没学,但是百度、谷歌大法无敌。 查查原理,再去做题。 经过一番查找,懂了原理,就总结了一下 简单说: 叶子结点:权值 a : 4 d :9 g : 1 f : 5 l : 1 0 : 7 5 : 9 { : 1 } ...

Lemon's blog 1万+

支付宝H5支付唤醒协议全解析:从alipays://到动态orderSuffix的抓取与拼接

本文深入解析支付宝H5支付唤醒协议,从alipays://协议设计到动态orderSuffix参数的抓取与拼接,详细介绍了支付宝H5支付的底层机制。内容包括协议架构剖析、动态令牌生成与捕获、浏览器兼容性解决方案以及安全机制设计,为开发者提供全面的技术指南和实践建议。

weixin_27972919的博客 3498

CTF密码学总结(二)

CTF 密码学总结 出人意料的flag: 指在题目中获取到了flag,但是这个flag可能长得不像flag,或者flag还要经过进一步的脑洞处理,而不是常规的解密处理。 非预期行为: 指解题中出现与预想结果不符合的一系列非预期行为,这基本说明了在中间或前面存在其他自己还没分析的操作。 冗余中锁定关键代码: 从后往前看,就是确定比较关键对象,从该对象开始排除其他无关变量,一步步找出与该对象有关的其它变量,最后串起找到的所有相关变量,然后开始逆向分析。 题目类型总结: 题目描述暗

沐一 · 林 的博客 5万+

CDD那些事 - DID and SecurityAccess

本文介绍了SecurityAccessSID27的安全访问配置流程:1.通过StateGroups添加Level2群组;2.在Classes定义L2子功能;3.配置4步解锁流程,选择对应解锁等级;4.在DiagnosticInstance设置请求响应。同时说明了DID配置的两种方式:在DIDs页面定义或通过Identification页面创建,前者定义更全面。文章还提到ServiceList支持view/edit模式,其中edit模式可配置DID的多服务支持(如同时支持SID22读取和SID2E写入),但该

ziteng21的博客 256

Vue3 + uniapp 踩坑:iOS 真机调试一直报错Maximum call stack size exceeded,和(in promise)MiniProgramError err的解决方法

不是你写错代码,是微信开发工具和 iOS 真机调试的兼容问题。开个空项目都报错,勾个设置就没问题,不是你,是工具的锅。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1267

【ctf】Crypto初步基础概要

这里是关于密码的整体概要,不管你是否喜欢ctf,只要你喜欢安全的,都可以进行学习和交流,也欢迎各位师傅的指点。

JacinLee的博客 1万+

PCB铺铜技巧如何铺铜经验总结

铺铜是指在PCB电气层添加整块的铜皮;铺铜包括电源层铺铜,地层铺铜和信号走线层空闲区域铺铜;铺铜是PCB设计的一个重要的环节。

fydar的博客 1万+

CTF密码学Crypto1

CTF密码学Crypto1.Morse code(摩尔斯密码)2. 栅栏密码3. 恺撒密码4.Ook!编码5.Brainfuck编码**3级标题四级标题五级标题六级标题 1.Morse code(摩尔斯密码) 特点: 用两种“符号”来表示字符:点(.)和划(-) 2. 栅栏密码 所谓栅栏密码,就是把要加密的明文分成N个一组,然后把每组的第1个字连起来,形成一段无规律的话。 不过栅栏密码本身有一个...

MikeCoke的博客 3169

YOLOv11改进 | 注意力篇 | YOLOv11引入24年动态卷积块注意力(Dynamic-CBAM),并构建C2PSA_DynamicCBAM

1.Dynamic-CBAM介绍1.1 摘要:重度抑郁症是一种普遍而严重的心理健康状况,对您的情绪,思想,行动和对世界的整体感知产生负面影响。由于抑郁症的症状不明显,确定一个人是否抑郁是很复杂的。然而,他们的声音可能是我们可以识别抑郁症迹象的因素之一。抑郁的人会表现出不适、悲伤,他们可能说话缓慢、颤抖,声音中失去情感。在这项研究中,我们提出了动态卷积块注意力模块(DynamicCBAM),用于在注意力-GRU网络中通过分析人类的音频信号来分类情感。

tsg6698的博客 1002

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

上一篇: 40多岁转行学了网络安全,能谋生吗?
下一篇: 程序员挖“洞”致富:发现一个漏洞,获赏 1272 万元!
程序员_大白
博客等级 码龄5年 1万+粉丝 4001原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值