根據(jù)參考文獻(xiàn)1知線生移位寄存器產(chǎn)生m序列的充要條件是特征多項(xiàng)式f(x)為本原多項(xiàng)式。而確立有限域上的本原多項(xiàng)式,主要有兩種方法:
...
-1(因?yàn)?span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;">α是本原元,所以n是使
:若G為一個(gè)階為n的有限循環(huán)群,g為對(duì)應(yīng)的生成元,則對(duì)整除n的每個(gè)整數(shù)k,G都存在一個(gè)唯一的階為k的循環(huán)子群H。
≡d (mod N)有解,則d的平方根中有一半的Jacobi符號(hào)為1,另一半Jacobi符號(hào)為-1;且僅有一個(gè)平方根為模N的二次剩余
另加密與明文異或的那部分實(shí)際是偽隨機(jī)比特發(fā)生器,因?yàn)槠椒侥構(gòu)成二次剩余類上的單向陷門置換,其最低有效位是核心斷言,故從s
,所以為概率加密,進(jìn)而由可證明安全定理(每個(gè)概率公鑰加密都是多項(xiàng)式安全的,及每個(gè)多項(xiàng)式安全的公鑰加密都是語(yǔ)義安全的)知滿足
)的分布是偽隨機(jī)的,在目標(biāo)密文前的解密詢問(wèn)會(huì)得到若干密文與明文對(duì),無(wú)論怎么構(gòu)造一對(duì)明文,任選其一加密得到的密文都不可區(qū)分。因此
如上構(gòu)造用到Blum數(shù)的上述推論,及基于大整數(shù)因子分解的困難假設(shè)。這里主要解釋下為什么由兩個(gè)Jacobi符號(hào)不同的平方根可計(jì)算大整數(shù)的素因子
從上面例子可以發(fā)現(xiàn),由二次剩余子群構(gòu)成的隨機(jī)數(shù)數(shù)列不一定是整周期的,對(duì)于N=33無(wú)論種子怎么選,都是整周期4;對(duì)于N=57若種子選-8或7則周期為2,選其它則為6。
圖靈機(jī)可識(shí)別的語(yǔ)言類,NPC表示NP完全問(wèn)題類,coNP表示NP的補(bǔ),coNPC表示NPC的補(bǔ)。確定型圖靈機(jī)是一種從不選擇移動(dòng)的特殊的非確定型圖靈機(jī),故自然有P屬于NP
周知內(nèi)聯(lián)是為了消除函數(shù)調(diào)用的代價(jià),即四大指令序列:調(diào)用前序列、被調(diào)者起始序列、被調(diào)者收尾序列、返回后序列。它們通常對(duì)應(yīng)到體系結(jié)構(gòu)調(diào)用者保存/恢復(fù)寄存器集合與被調(diào)者保存/恢復(fù)寄存器集合之約束。這個(gè)本質(zhì)也是內(nèi)聯(lián)的前提。試問(wèn)如果有某體系結(jié)構(gòu)比如S,它任意深度的函數(shù)調(diào)用代價(jià)幾乎為零,那么顯然內(nèi)聯(lián)是沒(méi)意義沒(méi)必要的。但是S可能存在嗎?我認(rèn)為不太可能。因?yàn)闄C(jī)器的資源比如寄存器集數(shù)量與堆棧空間是有限的,且調(diào)用需要知曉上下文,所以不能夠支持任意深度的調(diào)用,但是可以支持有限深度比如4層調(diào)用,這4層調(diào)用代價(jià)幾乎為零,假設(shè)再來(lái)一層,那么第5層調(diào)用代價(jià)就不為零了,這時(shí)如果內(nèi)聯(lián)第5層就變成4層調(diào)用,代價(jià)又幾乎為零。綜上所述,內(nèi)聯(lián)無(wú)論在何種體系結(jié)構(gòu),即使在一定深度內(nèi)沒(méi)意義也不會(huì)破壞性能。
體系結(jié)構(gòu)直接影響程序性能。主要體現(xiàn)在指令集、寄存器、cache三塊。它們對(duì)于編譯器實(shí)現(xiàn)代碼優(yōu)化必須都考慮,尤其cache比如內(nèi)聯(lián)優(yōu)化、循環(huán)展開、基本塊布局、函數(shù)重排,如果不是因?yàn)橛衏ache這玩意,內(nèi)聯(lián)優(yōu)化的復(fù)雜性會(huì)大為降低,因?yàn)椴挥每紤]代碼膨脹引起的副作用即cache缺失,只要評(píng)估函數(shù)的指令數(shù)與動(dòng)態(tài)執(zhí)行消耗的關(guān)系,指令數(shù)很少但執(zhí)行耗費(fèi)很多時(shí)鐘周期的,則不宜內(nèi)聯(lián),尤其函數(shù)為非葉子結(jié)點(diǎn);指令數(shù)很多但執(zhí)行耗費(fèi)較少的,則可僅內(nèi)聯(lián)其中的快速路徑代碼。因現(xiàn)實(shí)存在cache這玩意,就必須權(quán)衡代碼膨脹帶來(lái)的副作用,是否能接受一定的膨脹,需要精確評(píng)估,構(gòu)建函數(shù)調(diào)用頻率與其靜態(tài)調(diào)用位置的矩陣,計(jì)算收益比如平均執(zhí)行一次的耗時(shí)是否減少,若收益為正且明顯則可內(nèi)聯(lián),否則不宜內(nèi)聯(lián)。
有些編譯器為了簡(jiǎn)單處理,不會(huì)內(nèi)聯(lián)帶靜態(tài)變量的函數(shù)哪怕指令數(shù)很少,或者內(nèi)聯(lián)不太正確比如
(詳見下文)。其實(shí)單從技術(shù)上可以做到,不過(guò)要復(fù)雜些,復(fù)雜在于鏈接器的協(xié)作。為了保證函數(shù)級(jí)靜態(tài)變量的語(yǔ)義,編譯時(shí)要預(yù)留全局唯一標(biāo)志與構(gòu)造函數(shù)的占位符,在調(diào)用者體內(nèi)插入對(duì)全局唯一標(biāo)志的(位)判斷(標(biāo)志字的一位對(duì)應(yīng)一個(gè)靜態(tài)變量,表明是否已構(gòu)造或初始化賦值)、構(gòu)造函數(shù)調(diào)用/初始化賦值、置位標(biāo)志,而鏈接時(shí)要確定全局唯一標(biāo)志及構(gòu)造函數(shù)的地址。靜態(tài)變量、全局唯一標(biāo)志放于可執(zhí)行文件的數(shù)據(jù)區(qū),全局唯一構(gòu)造/初始化及析構(gòu)函數(shù)放于代碼區(qū),具體布局位置可以靈活,比如. data. static_obj,. text. obj. ctor/dtor。如果這種函數(shù)性能影響較大需要內(nèi)聯(lián)優(yōu)化,而編譯器不支持,有個(gè)替代的辦法是用全局變量或文件/類級(jí)別的靜態(tài)變量,輔以對(duì)應(yīng)標(biāo)志處理一次性構(gòu)造或初始化賦值(必要時(shí)將這處理封裝為一個(gè)函數(shù)以確保目標(biāo)函數(shù)被內(nèi)聯(lián)),可達(dá)到同樣效果不足之處是作用域擴(kuò)大了。
:這里指代碼實(shí)現(xiàn)層面(非數(shù)學(xué)優(yōu)化層面),使用寄存器優(yōu)化,即主密鑰/輪密鑰、敏感數(shù)據(jù)比如中間/臨時(shí)變量必須存于寄存器,明文/密文放在內(nèi)存(若有夠用的寄存器則放寄存器),主密鑰用特權(quán)寄存器(為支持長(zhǎng)期存儲(chǔ),比如調(diào)試寄存器、MSR寄存器),輪密鑰和敏感數(shù)據(jù)用通用寄存器。那么怎么做?穩(wěn)妥快捷的方法是用匯編或內(nèi)聯(lián)匯編,手工編排寄存器即構(gòu)建密鑰與敏感數(shù)據(jù)到寄存器集合的映射,若用普通的匯編指令,則寄存器的映射比較自由;若用專用的加密指令,則映射相對(duì)受限。如果用高級(jí)語(yǔ)言比如c/c++開發(fā),問(wèn)題在于
關(guān)鍵字非強(qiáng)制生效,即使強(qiáng)制的,編譯器優(yōu)化(比如公共子表達(dá)式消除)產(chǎn)生的中間變量及寄存器分配策略不完全可控,需要修改編譯器比如
強(qiáng)制某些變量必須分配(特定的)寄存器,為通用性要從編程語(yǔ)言語(yǔ)法屬性到目標(biāo)機(jī)器代碼生成都改動(dòng)支持,這個(gè)方法實(shí)現(xiàn)成本有點(diǎn)大。下面是摘自LLVM X86RegisterInfo.td的部分寄存器
1 // 32-bit registers
2 let SubRegIndices = [sub_16bit, sub_16bit_hi], CoveredBySubRegs = 1
in {
3 def EAX : X86Reg<"eax", 0, [AX, HAX]>, DwarfRegNum<[-2, 0, 0]>;
4 def EDX : X86Reg<"edx", 2, [DX, HDX]>, DwarfRegNum<[-2, 2, 2]>;
5 def ECX : X86Reg<"ecx", 1, [CX, HCX]>, DwarfRegNum<[-2, 1, 1]>;
6 def EBX : X86Reg<"ebx", 3, [BX, HBX]>, DwarfRegNum<[-2, 3, 3]>;
7 def ESI : X86Reg<"esi", 6, [SI, HSI]>, DwarfRegNum<[-2, 6, 6]>;
8 def EDI : X86Reg<"edi", 7, [DI, HDI]>, DwarfRegNum<[-2, 7, 7]>;
9 def EBP : X86Reg<"ebp", 5, [BP, HBP]>, DwarfRegNum<[-2, 4, 5]>;
10 def ESP : X86Reg<"esp", 4, [SP, HSP]>, DwarfRegNum<[-2, 5, 4]>;
11 def EIP : X86Reg<"eip", 0, [IP, HIP]>, DwarfRegNum<[-2, 8, 8]>;
12 }
13
14 // X86-64 only, requires REX
15 let SubRegIndices = [sub_16bit, sub_16bit_hi], CoveredBySubRegs = 1
in {
16 def R8D : X86Reg<"r8d", 8, [R8W,R8WH]>;
17 def R9D : X86Reg<"r9d", 9, [R9W,R9WH]>;
18 def R10D : X86Reg<"r10d", 10, [R10W,R10WH]>;
19 def R11D : X86Reg<"r11d", 11, [R11W,R11WH]>;
20 def R12D : X86Reg<"r12d", 12, [R12W,R12WH]>;
21 def R13D : X86Reg<"r13d", 13, [R13W,R13WH]>;
22 def R14D : X86Reg<"r14d", 14, [R14W,R14WH]>;
23 def R15D : X86Reg<"r15d", 15, [R15W,R15WH]>;
24 }
25
26 // 64-bit registers, X86-64 only
27 let SubRegIndices = [sub_32bit]
in {
28 def RAX : X86Reg<"rax", 0, [EAX]>, DwarfRegNum<[0, -2, -2]>;
29 def RDX : X86Reg<"rdx", 2, [EDX]>, DwarfRegNum<[1, -2, -2]>;
30 def RCX : X86Reg<"rcx", 1, [ECX]>, DwarfRegNum<[2, -2, -2]>;
31 def RBX : X86Reg<"rbx", 3, [EBX]>, DwarfRegNum<[3, -2, -2]>;
32 def RSI : X86Reg<"rsi", 6, [ESI]>, DwarfRegNum<[4, -2, -2]>;
33 def RDI : X86Reg<"rdi", 7, [EDI]>, DwarfRegNum<[5, -2, -2]>;
34 def RBP : X86Reg<"rbp", 5, [EBP]>, DwarfRegNum<[6, -2, -2]>;
35 def RSP : X86Reg<"rsp", 4, [ESP]>, DwarfRegNum<[7, -2, -2]>;
36
37 // These also require REX.
38 def R8 : X86Reg<"r8", 8, [R8D]>, DwarfRegNum<[ 8, -2, -2]>;
39 def R9 : X86Reg<"r9", 9, [R9D]>, DwarfRegNum<[ 9, -2, -2]>;
40 def R10 : X86Reg<"r10", 10, [R10D]>, DwarfRegNum<[10, -2, -2]>;
41 def R11 : X86Reg<"r11", 11, [R11D]>, DwarfRegNum<[11, -2, -2]>;
42 def R12 : X86Reg<"r12", 12, [R12D]>, DwarfRegNum<[12, -2, -2]>;
43 def R13 : X86Reg<"r13", 13, [R13D]>, DwarfRegNum<[13, -2, -2]>;
44 def R14 : X86Reg<"r14", 14, [R14D]>, DwarfRegNum<[14, -2, -2]>;
45 def R15 : X86Reg<"r15", 15, [R15D]>, DwarfRegNum<[15, -2, -2]>;
46 def RIP : X86Reg<"rip", 0, [EIP]>, DwarfRegNum<[16, -2, -2]>;
47 }
48 
49 // XMM Registers, used by the various SSE instruction set extensions.
50 def XMM0: X86Reg<"xmm0", 0>, DwarfRegNum<[17, 21, 21]>;
51 def XMM1: X86Reg<"xmm1", 1>, DwarfRegNum<[18, 22, 22]>;
52 def XMM2: X86Reg<"xmm2", 2>, DwarfRegNum<[19, 23, 23]>;
53 def XMM3: X86Reg<"xmm3", 3>, DwarfRegNum<[20, 24, 24]>;
54 def XMM4: X86Reg<"xmm4", 4>, DwarfRegNum<[21, 25, 25]>;
55 def XMM5: X86Reg<"xmm5", 5>, DwarfRegNum<[22, 26, 26]>;
56 def XMM6: X86Reg<"xmm6", 6>, DwarfRegNum<[23, 27, 27]>;
57 def XMM7: X86Reg<"xmm7", 7>, DwarfRegNum<[24, 28, 28]>;
58
59 // X86-64 only
60 def XMM8: X86Reg<"xmm8", 8>, DwarfRegNum<[25, -2, -2]>;
61 def XMM9: X86Reg<"xmm9", 9>, DwarfRegNum<[26, -2, -2]>;
62 def XMM10: X86Reg<"xmm10", 10>, DwarfRegNum<[27, -2, -2]>;
63 def XMM11: X86Reg<"xmm11", 11>, DwarfRegNum<[28, -2, -2]>;
64 def XMM12: X86Reg<"xmm12", 12>, DwarfRegNum<[29, -2, -2]>;
65 def XMM13: X86Reg<"xmm13", 13>, DwarfRegNum<[30, -2, -2]>;
66 def XMM14: X86Reg<"xmm14", 14>, DwarfRegNum<[31, -2, -2]>;
67 def XMM15: X86Reg<"xmm15", 15>, DwarfRegNum<[32, -2, -2]>;
68
69 def XMM16: X86Reg<"xmm16", 16>, DwarfRegNum<[67, -2, -2]>;
70 def XMM17: X86Reg<"xmm17", 17>, DwarfRegNum<[68, -2, -2]>;
71 def XMM18: X86Reg<"xmm18", 18>, DwarfRegNum<[69, -2, -2]>;
72 def XMM19: X86Reg<"xmm19", 19>, DwarfRegNum<[70, -2, -2]>;
73 def XMM20: X86Reg<"xmm20", 20>, DwarfRegNum<[71, -2, -2]>;
74 def XMM21: X86Reg<"xmm21", 21>, DwarfRegNum<[72, -2, -2]>;
75 def XMM22: X86Reg<"xmm22", 22>, DwarfRegNum<[73, -2, -2]>;
76 def XMM23: X86Reg<"xmm23", 23>, DwarfRegNum<[74, -2, -2]>;
77 def XMM24: X86Reg<"xmm24", 24>, DwarfRegNum<[75, -2, -2]>;
78 def XMM25: X86Reg<"xmm25", 25>, DwarfRegNum<[76, -2, -2]>;
79 def XMM26: X86Reg<"xmm26", 26>, DwarfRegNum<[77, -2, -2]>;
80 def XMM27: X86Reg<"xmm27", 27>, DwarfRegNum<[78, -2, -2]>;
81 def XMM28: X86Reg<"xmm28", 28>, DwarfRegNum<[79, -2, -2]>;
82 def XMM29: X86Reg<"xmm29", 29>, DwarfRegNum<[80, -2, -2]>;
83 def XMM30: X86Reg<"xmm30", 30>, DwarfRegNum<[81, -2, -2]>;
84 def XMM31: X86Reg<"xmm31", 31>, DwarfRegNum<[82, -2, -2]>;
85
86 // YMM0-15 registers, used by AVX instructions and
87 // YMM16-31 registers, used by AVX-512 instructions.
88 let SubRegIndices = [sub_xmm]
in {
89 foreach Index = 0-31
in {
90 def YMM#Index : X86Reg<"ymm"#Index, Index, [!cast
("XMM"#Index)]>,
91 DwarfRegAlias("XMM"#Index)>;
92 }
93 }
94
95 // ZMM Registers, used by AVX-512 instructions.
96 let SubRegIndices = [sub_ymm] in {
97 foreach Index = 0-31 in {
98 def ZMM#Index : X86Reg<"zmm"#Index, Index, [!cast("YMM"#Index)]>,
99 DwarfRegAlias("XMM"#Index)>;
100 }
101 }
102 

103 // Debug registers
104 def DR0 : X86Reg<"dr0", 0>;
105 def DR1 : X86Reg<"dr1", 1>;
106 def DR2 : X86Reg<"dr2", 2>;
107 def DR3 : X86Reg<"dr3", 3>;
108 def DR4 : X86Reg<"dr4", 4>;
109 def DR5 : X86Reg<"dr5", 5>;
110 def DR6 : X86Reg<"dr6", 6>;
111 def DR7 : X86Reg<"dr7", 7>;
112 def DR8 : X86Reg<"dr8", 8>;
113 def DR9 : X86Reg<"dr9", 9>;
114 def DR10 : X86Reg<"dr10", 10>;
115 def DR11 : X86Reg<"dr11", 11>;
116 def DR12 : X86Reg<"dr12", 12>;
117 def DR13 : X86Reg<"dr13", 13>;
118 def DR14 : X86Reg<"dr14", 14>;
119 def DR15 : X86Reg<"dr15", 15>;
120 

121 def GR32 : RegisterClass<"X86", [i32], 32,
122 (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP,
123 R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D)>;
124
125 // GR64 - 64-bit GPRs. This oddly includes RIP, which isn't accurate, since
126 // RIP isn't really a register and it can't be used anywhere except in an
127 // address, but it doesn't cause trouble.
128 // FIXME: it *does* cause trouble - CheckBaseRegAndIndexReg() has extra
129 // tests because of the inclusion of RIP in this register class.
130 def GR64 : RegisterClass<"X86", [i64], 64,
131 (add RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
132 RBX, R14, R15, R12, R13, RBP, RSP, RIP)>;
:為保障安全就復(fù)雜了,由于密鑰及敏感數(shù)據(jù)存于寄存器,首先要防止寄存器交換/拷貝到內(nèi)存(為避免讀取內(nèi)存的冷啟動(dòng)攻擊、基于cache的側(cè)信道攻擊)的一切可能因素,比如進(jìn)程調(diào)度、由信號(hào)或異步中斷引起的處理器模式切換、系統(tǒng)休眠,如果在用戶態(tài)實(shí)現(xiàn)加解密,就避免不了被調(diào)度或切換,因?yàn)閱魏松喜豢赡苤贿\(yùn)行加解密進(jìn)程,所以得實(shí)現(xiàn)在內(nèi)核態(tài)。這樣一來(lái)就要在加解密中禁止搶占與中斷,考慮到系統(tǒng)響應(yīng),禁止的粒度不能過(guò)大最小為一個(gè)分組,分組加解密前禁止搶占與中斷(比如調(diào)用linux內(nèi)核接口
)前必須清零寄存器。在系統(tǒng)休眠時(shí),禁止寄存器復(fù)制到內(nèi)存,休眠恢復(fù)時(shí)在所有用戶態(tài)進(jìn)程恢復(fù)前執(zhí)行密鑰初始化,同理系統(tǒng)啟動(dòng)時(shí)的密鑰初始化也得在用戶態(tài)進(jìn)程運(yùn)行前執(zhí)行。其次要防止其它用戶態(tài)進(jìn)程/內(nèi)核線程/中斷服務(wù)程序讀寫寄存器尤其特權(quán)寄存器(為避免用戶態(tài)或內(nèi)核態(tài)rootkit),所以要修改內(nèi)核,過(guò)濾相關(guān)系統(tǒng)調(diào)用比如linux的
。對(duì)于不可屏蔽的中斷靠禁止是無(wú)效的,只能修改中斷處理程序避免寄存器中的密鑰數(shù)據(jù)被擴(kuò)散到內(nèi)存,比如在中斷處理函數(shù)入口處清零相關(guān)寄存器。綜上基于已知代碼修改的防御不能防御惡意加載/修改代碼之類的攻擊,比如動(dòng)態(tài)安裝的內(nèi)核模塊/驅(qū)動(dòng),但可有效防御冷啟動(dòng)攻擊、只讀DMA攻擊、基于cache的側(cè)信道攻擊、用戶態(tài)權(quán)限的軟件攻擊、內(nèi)核態(tài)的僅運(yùn)行已有代碼的軟件攻擊