1. 程式人生 > >openssl加解密原理

openssl加解密原理

gpg ca openssl libssl 加密和解密 對稱加密

加密算法和協議:
一、加密和解密簡介
二、OpenSSL和GPG
三、對稱加密的密鑰分發
四、非對稱加密
五、SSL/TLS的實現
六、OpenSSL應用
七、構建私有CA
八、證書簽署案例

一、加密和解密簡介
對稱加密:數據加密傳輸(保密性),DES,3DES,AES,
公鑰加密:身份驗證,密鑰交換,數字簽名(特征碼加密) ,(不常用,比對稱加密慢3個數量級)
:RSA,DSA
單向加密:保證數據的完整性,依賴於數字簽名
:sha[1,224,256},MD5
密鑰交換:DH,RSA,ECDH(橢圓曲線DH),ECDHE(臨時橢圓曲線DH)

數字簽名:用自己的信息,加密要發送的數據的特征碼
//一般數字簽名,簽的是要加密的數據的特征碼
目的:驗證發送者的身份
http需要依賴於SSL/TLS--->HTPPS

TCP/IP層:
應用層 ||資源子網
===========================================SSL:半層在應用層和傳輸層之間
傳輸層 ||通信子網
網絡層
主機到網絡層:{數據鏈路層+物理層}
===========================================

資源子網+通信子網
內核空間+用戶空間

//早期的數據傳輸是不加密的,因此出現了SSL,提供調用實現加密,不加密也可以實現通信
//SSL能完成秘鑰分發和加解密功能,SSL是一種規範和協議
//程序員開發的時候:調用該庫
//該庫功能:網絡方面{秘鑰分發},加解密

OSI七層:
通信子網的功能:由內核實現
資源子網:在用戶空間是如何實現:
諸多協議,程序,服務端,客戶端
應用程序:自己負責報文封裝,應用層首部添加等
:應用程序的具體實現靠的是應用程序自身,應用程序的進程負責封裝應用層的報文
:然後:到/傳輸層/網絡層/主機到網絡層//層層封裝---->解封裝-->交給應用層註冊使用該端口的進程

HTTP調用SSL成為了HTTPS
http-->https(支付的時候用)-->全棧https
全棧https //避免惡意插入廣告和惡意信息竊取

傳輸層協議:TCP,UDP,SCTP//流控傳輸協議,
port:進程地址,進程向內核註冊使用某端口,(獨占)
socket=ip:port是標識進程地址的
主機間的通信:其實就是主機上的進程間的通信
進程間通信的方式:
同一主機上的通信:基於IPC機制,message queue,shm,semerphor[旗語],..
同一主機上也可以使用socket進行通信
不同主機上的通信:socket=ip:port,C:ip+port和S:ip+port//成對出現進行通信
cip:port《----》sip:port
完成通信:
server端需要打開一個端口,監聽該端口(ip:port)
1-1024:固定端口
1025-3999:半隨機
4000-6500:隨機
具體查看:#cat /proc/sys/net/ipv4/ip_local_port_range,

通信安全的目標:
保密性:confidentiality
完整性:integrity
數據完整性
系統完整性
可用性:availability
攻擊類型:
威脅保密性攻擊:竊聽,通信量分析
威脅完整性的攻擊:更改、偽裝、重放[備份多次發送]、否認
威脅到可用性攻擊:拒絕服務DOS(deny of service),DDOS
解決方案:
技術(加密和解密)
服務(用於抵禦攻擊的服務,也即是為了上述安全目標而特地設計的安全服務)

加密和解密
傳統加密方法:替代加密算法(替換某字母或者後退幾個)、置換加密算法()
現代加密方法:塊加密方法(切割成塊,然後單獨加密,各塊之間進行異或運算等):數據竊取者必須拿到完整的數據和才可以
服務:
認證機制:
訪問控制機制:
密鑰算法和協議
對稱加密
非對稱加密( 公鑰加密)
單向加密
認證協議

二、OpenSSL和GPG
Linux系統加密:OpenSSL(SSL),GPG(pgp)
OpenSSL:三部分組成
1.加密解密庫 libencrypt,
2.libssl庫 //安全通信,加密模塊應用庫,實現了tls和ssl
3.openssl 命令行工具,實現加密解密,以及實現ssl安全通信
//90%都是調用openssl來實現安全
OpenSSL出現了一個大的漏洞 //一個開源組織維護,只靠捐獻進行生存-致敬
https://www.cnblogs.com/milantgh/p/3665901.html //openssl漏洞簡介
加密算法和協議
對稱加密:加密和解密使用同一個密鑰,//但是加密和解密算法可能不同
DES:data encryption standard//數據加密標準
64bit明文加密為64bit密文,解密:64bit密文解密為64bit明文
8Byte為一個塊 //已經被破解
3DES:Triple DES //3個數量級,一個數量級10倍
AES:Advanced Encryption Standard
支持變長密鑰:128.192,256,384bit密鑰
Blowflsh Twoflsh IDEA RC6 CAST5
特性:
1.加密、解密使用同一個密鑰
2.將原始數據分割成為固定大小的塊,逐個進行加密
缺陷:
1.密鑰過多 //s被多個用戶同時訪問,需要同時保持n個密鑰,但是又不能相同
2.密鑰分發困難 //如何拿到密碼,密鑰交換基於算法實現
非對稱加密://稍後介紹
gpg用法://這裏不做介紹,請自行理解

三、對稱加密的密鑰分發
1.分發的方式
  1、A選擇一個密鑰後以物理的方式傳遞給B
  2、第三方選擇密鑰後物理地傳給A和B
  3、如果A和B先前或最近使用過一個密鑰,則一方可以將 新密鑰用舊密鑰加密後發送給另一方
  4、如果A和B到第三方C有加密連接,則C可以在加密連接上發送密鑰給A、B
分析:
1和2需要人工交付
3,一旦攻擊者獲得一個密鑰,則後續所有的密鑰都不再安全,可以進行重放攻擊
4.需要密鑰分發中心,廣泛使用
2.分發方案
原理:密鑰分發中心KDC和每個終端用戶都共享一對唯一的主密鑰(用物理的方式傳遞,如U盾)。
終端用戶每次回話,都要向KDC申請唯一的會話密鑰,會話密鑰通過與KDC共享的主密鑰的主密鑰來完成傳遞

技術分享圖片

1、A以明文形式向KDC發送會話密鑰請求包。包括通話雙方A、B的身份以及該次傳輸的唯一標識N1,稱為臨時交互號(nonce)。
  臨時交互號可以選擇時間戳、隨機數或者計數器等。KDC可根據臨時交互號設計防重放機制。
2、KDC返回的信息包括兩部分。
  第一部分是A想獲取的信息,用A的主密鑰KA加密,包括通話密鑰Ks和KDC收到的請求包內容用以驗證消息到達KDC前是否被修改或者重放過。
  第二部分是B想獲取的信息,用B的主密鑰KB加密,包括通話密鑰Ks和A的身份。A收到後這部分消息便原樣發給B。
3、為保證A發給B的會話密鑰信息未被重放攻擊,A、B使用會話密鑰進行最後的驗證。
  B使用新的會話密鑰Ks加密臨時交互號N2並發給A。A對N2進行一個函數變換後,用會話密鑰發給B驗證。

  對於大型網絡,可以建立KDC的層次體系來使得主密鑰分發的開銷最小化。


四、非對稱加密
1.公鑰加密:密鑰分為公鑰和私鑰
公鑰:從私鑰中提取,公開給所有人:pubkey
私鑰:通過工具創建,使用者自己留存,必須保存期私密性:private key
特點:用公鑰加密的數據,只能使用與之配對兒的私鑰解密;反之亦然

用途:數字簽名:主要用於讓接收方確認發送方的身份
密鑰交換:發送方用對方公鑰加密一個對稱密鑰,並發送給對方
數據加密:

數據發送的過程中[]:用對方的公鑰加密,傳輸
身份認證的過程中[數字簽名]:用自己的私鑰加密,然後發給對方,對方用我們的公鑰能夠解密,完成身份認證

算法:RSA,DSA,ELGamal
DSS(DSA):digital signatur Standard/Algorthm
DSA:僅能備用來簽名,不能加解密
RSA:既能簽名,又能加解密

2.單項加密:
只能加密,不能解密 //提取數據指紋[特征碼]信息
特征碼:定長輸出,雪崩效應;
功能:完整性,沒有被修改過
算法:
md5:message digest version5 :128bit
sha1:secure hash algorithm 1 :160bits
sha224,sha256,sha384,sha512

密鑰IKE:internet key exchange //密鑰交換
公鑰加密:
DH(deffle-hellman):
DH算法:密碼本身不必在網絡上傳送,就能夠協商生成
A:p,g
B:p,g //雙方協商生成p,g等數組,明文交換,別人能夠看到

A:x //這個數據是私自生成的,B不知道,其他人也不知道
1.-->p^x%g===>B
2.(p^y%g)^x==p^xy%g
B:y
1.-->p^y%g===>A
2.(p^x%g)^y===p^xy%g //和A2的結果是一樣的,這個就是密鑰


公鑰加密有風險,因為密鑰是在網絡上傳送的,所以更傾向於DH

3.公鑰加密過程:
1.加密特征碼://保證數據完整性和身份驗證
利用單項加密算法:提取特征碼,定長輸出 //然後使用自己的私鑰,加密特征碼
註意:不能保證數據的保密性,因為其他人也可以進行解密特征碼
bob用同樣的算法,解密特征碼,一致則完整以及身份得到驗證
註意:加密特征碼的過程,就稱為生成數字簽名的過程
2.A生成一個一次性的對稱密鑰,加密整個數據,
B用A的pkey加密對稱密鑰,附加到數據後,發送給A
3.A先用自己的私鑰解密數據,得到對稱密鑰,進行解密//密鑰交換
用B的公鑰解密簽名,能解密則身份得到驗證,
然後用單項加密算法,得到對稱碼,對比驗證數據保密性

4.B想和A進行通信
B用單項加密算法得到特征碼,用自己的私鑰加密特征碼
[特征碼{B的私鑰加密}#數據{對稱密鑰加密}#對稱密鑰{對方的公鑰}]最後用A的公鑰加密,一起發送給A

設計算法:對稱加密[數據傳輸快速],單項加密[完整性],單向加密[身份驗證]

身份認證:B用自己的私鑰加密特征碼,A用B的pkey能夠解密,則認證成功
數字簽名:B用自己的私鑰加密特征碼的過程,就叫做數字簽名
數字簽名就是為了完整身份認證
簽名:在特征碼上用私鑰加密就叫簽名
密鑰交換:用對方的公鑰加密自己生成的對稱密鑰,只有對方能夠解密
//對稱加密的效率高,速度快,公鑰加密雖然安全,但是加密速度慢,效率不高
//之後使用對稱密鑰,加解密就可以了

1.計算特征碼,B用私鑰加密特征碼,並將結果附加到數據後面,B生成對稱密鑰,加密整個數據
獲取A公鑰,使用對方的公鑰加密對稱密鑰,附加到數據包後面,發送給A
[數據|s特征碼] ==>對稱密鑰加密==>{[數據|s特征碼|}{ps對稱密鑰]
2.A先用自己的私鑰解密對稱密鑰:ps對稱密鑰
解密 [數據|特征碼]
用對方的公鑰解密 [s特征碼]
用同樣的算法計算特征碼 [數據] //完整性

註意:對稱加密的對象{數據|s特征碼},對稱密鑰是單獨加密放到後面的

5.B和A通信的中間人攻擊:
之前的bug:不能預防中間人攻擊 //A---{b}-----c
中間人復制一份,然後實現A和c的通信
b把自己的公鑰發送給A告訴A,自己就是c
B再把自己的公鑰發送給c,告訴c自己就是A
方案:CA:可靠的公鑰獲取機構 //Certificate Authority,認證授權
證書:可以理解為公鑰

B得到A的公鑰後
1.驗證證書的內容是否合法
2.是否是受信任的CA頒發的
++++++++++++++++++++++++++++++++++++++++++
CA
/ \
/ \
/ \
B ------------A

++++++++++++++++++++++++++++++++++++++++++
PKI:以CA為中心的密鑰分發:public key infrastructure
公鑰基礎設施:
簽證機構:CA
註冊機構:RA
證書吊銷列表:CRL //recovery回收
證書存取庫:cdb
X.509 v3版 //定義證書的格式和標準,以及協議標準
版本號:證書版本
序列號:第幾個證書
簽名算法ID:用什麽算法的簽名
發行者名稱:CA自己的名字
有效期限:

主體名稱:
主體公鑰:
發行者的唯一標識:CA的唯一標識
主體的唯一標識:
擴展信息
發行者的簽名:CA的簽名,單項加密,用自己的私鑰加密

用CA驗證他人的身份
用CA的公鑰解密,CA的簽名,
用同樣的加密算法,加密證書,取得特征碼,與解密的特征碼[簽名]對比
檢查證書的有效期
驗證證書的主體名稱
檢查證書是否被吊銷

證書的內容:
有效期
CA的簽名//CA私鑰加密單項加密該數據後的特征碼,A獲取CA的公鑰,然後解密就可以
CA會自己先給自己發證書,發給別人
//如何獲取CA的證書:

CA的根證書,是OS自帶的,MicroSoft是自帶的,但是Linux是沒有的,需要自帶
CA還需要有證書吊銷列表

HTTPS//相當於http調用ssl代為建立通道進行通信

SSL通話過程:
1.發送hello,對方回復 //協商單項加密,對稱加密,公鑰加密算法
2.向server請求證書
3.client驗證證書,但是client不會發送自己的證書給server,因為有的client是沒有的
//server也是不用擔心什麽人來訪問的
//在網銀的時候可能會用到:電子密碼,U盾(個人證書)
4.客戶端使用生成隨機數:對稱密鑰,用對方的公鑰加密後發給對方
server用這個密碼加密client請求的頁面,
5.client請求斷開,server確認斷開,然後斷開

SSL:secure sockets layer //網警公司擁有版權,
Netspace:1994
google,據說有漏洞
v1,v2.0存在漏洞,v3:1996使用了很長時間
TLS:transport layer secure //仿照SSL,二者基本兼容,
IETF:1999發布
v1.0,v1.1,v1.2,v1.3:2014 //
由於SSLv3出現了很大漏洞,因此,建議使用TLS,但是並未所有的網站都支持TLS

分層設計:
1.最底層:基礎算法原語的實現,aes,rsa,md5等
2.向上一層:各種算法的實現
3.再向上一層:組合算法實現的半成品
4.用各種組件拼裝而成的各種成品密碼學協議軟件
協議的開源實現:openssl

階段:對稱密鑰用對方公鑰加密階段--->DH算法階段--->CA階段
DH階段,不能防範中間人攻擊

五、SSL/TLS的實現
SSL/TLS //知識一個協議
SSL:安全套接字層,v1,v2,v3現用
v3也發現有缺陷,但是是主流 //網警自己開發和維護
TLS:傳輸層安全,1.3,1.5 //將來很有可能為主流

實現:
OpenSSL:
libcrypto庫:加密和解密的
libssl庫:實現ssl功能的
openssl:命令行工具
SSL會話主要三步:
1.client向server索要並驗證證書
2.雙方協商生成“會話密鑰”
3.雙方采用"會話密鑰"進行加密

SSL handshake protocol:
第一階段:clientHello //第一步
client發送支持的協議版本:比如tsl 1.2
客戶端生成一個隨機數,稍後用於生成“會話密鑰”
支持的加密算法,比如AES,RSA;
支持的壓縮算算法
第二階段:server hello
確認使用的加密通信協議版本,比如tls1.2;//
服務器段生成一個隨機數,稍後用於生成”會話密鑰“
確認使用的加密方法
服務器證書;
//索要客戶端證書
第三階段:
驗證server證書;(發證機構、證書完整性、證書持有者、證書有效期、吊銷列表)
在確認無誤後,取出其公鑰
發送以下信息給服務器端
一個隨機數:用於server上的數據加密
編碼變更通知;
客戶端握手結束通知;
第四階段:
收到clinet發來的第二個隨機數,會話的第三個隨機數pre-master-key,計算生成本次會話所用到的“會話密鑰” //避免隨機數被猜測
向客戶端發送如下信息:
編碼變更通知;表示隨後的信息,都將使用對方商定的加密方法和密鑰發送
服務器握手接受通知

PKI:公鑰基礎設施
簽證機構:CA
註冊機構:RA
證書吊銷列表:CRL
證書存取庫:cdb

申請註冊機構:威瑞信等

六、OpenSSL應用
組件:libcrypto,libssl主要由開發者使用
openssl:多用途命令行工具
openssl 三類子命令
1.標準命令
ca
rand //生成隨機數
rsa
x509
genrsa:生成rsa算法的密鑰對
gendsa:生成dsa密鑰對
req:請求簽名
2.消息摘要:dgst
3.ciper command:加密命令:enc

對稱加密:
工具:openssl enc,gpg
支持的算法:3des,aes,blowfisk,towfish
what is enc //man enc 就可以獲取幫助信息
openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a/-base64]
-cipername:加密算法的名稱
-a base64編碼格式,不加-a使用的是二進制編碼
openssl enc -des3 -e -a -salt -in fstab -out fstab.enc
openssl enc -des3 -d -a -salt -in fstab.enc -out fstab
-a 不可少
-des3 再解密的時候也不能少,否則可能會亂碼
單項加密:
openssl dgst,gpg命令也可以md5sum,sha1sum,sha224sum
openssl dgst -md5 fstab
md5sum fstab
生成密碼工具
passwd,
whatis passwd
man sslpasswd
openssl passwd [-crypt] [-1] [-salt string] [-stdin] {password}
-1:md5
openssl passwd -1 -salt 12345678 -stdin
生成隨機數:
openssl rand
whatis rand
man rand
openssl rand -base64 64 //生成64位,base64編碼格式的隨機數
-hex //16進制,只有0-f
openssl passwd -1 -salt $(openssl rand -hex 4)
公鑰加密:
加密解密
算法:RSA,ElGamal
工具:openssl rsautl,gpg
數字簽名
算法:RSA,DSA,ELG,ELGamal
工具:openssl rsautl,gpg
密鑰交換
算法:DH

公鑰加密實現:
1.openssl genrsa 1024 > /tmp/a.out //生成私鑰
openssl genrsa -out /tmp/a.out 1024
(umask 077;openssl genrsa -out /tmp/mkey.pri 1024)
//放在括號中命令,要在子shell中運行,不會影響其他shell的運行,影響其他shell的umask
2.提取公鑰
openssl rsa -in /tmp/mykey.pri -pubout
openssl rsa -in my.pk -pubout > my.pub //-out也可保存


Linux系統上隨機數生成器:
/dev/random :僅從熵池返回隨機數;隨機數用盡,阻塞;
/dev/urandom:從熵池返回隨機數,隨機數用盡,會利用軟件生成偽隨機數,非阻塞
偽隨機數不安全
熵池:內核維護的存儲了大量的隨機數,剛開始是空的
來源:
硬盤IO中斷的時間間隔;
鍵盤IO中斷的時間間隔;兩次擊鍵的間隔
方法:一旦用盡,敲鍵盤或者復制文件到硬盤(硬盤IO)
CA:
1.公共信任的CA,私有CA
2.建立私有CA
建立私有CA
openssl:私有CA
OpenCA:公有CA

openssl配置文件
cat /etc/pki/tls/opessl.cnf
CA/certs:已經頒發的CA證書 $# Where the issued certs are kept
CA/crl:證書吊銷列表
CA/newcerts:默認新證書位置
CA/index.txt :數據庫索引文件

CA/serial:當前序列號,已經發到第幾個了
CA/cacert.pem :CA的自簽證書
CA/crlnumber :當前證書吊銷序列號

CA/crl.pem :當前CRL
CA/private/cakey.pem :CA的私鑰
七、構建私有CA
在確定配置為CA的服務器上生成一個自簽證書,並為CA提供所需要的目錄及文件即可
1.生成私鑰CA/private/cakey.pem
(umask 077;openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096)
註:cakey.pem要求默認放在CA/private中
2.生成自簽證書:CA/certs/
註:如果不是自簽,就不需要加x509
country name:CN
province name:Henan
locality:Henan
Default Company:MingTian
Unit Name:Ops
Common Name:ca.mingtian.com
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3655
-new生成新的證書
-x509生成自簽格式證書,專用於創建私有CA時
-key:生成請求時用到的私有文件路徑
-out:生成的請求文件路徑;如果自簽操作將直接生成簽署過的證書
-days:證書的有效時長,單位days

3.提供所需的目錄及文件
mkdir /etc/pki/CA/{crl,certs,newcerts}
touch /etc/pki/CA/{serial,index.txt}
echo 01 > /etc/pki/CA/serial
三個目錄兩個文件

請求簽署證書
1.client:192.168.4.109
cd /etc/httpd/ssl
(umask 077;openssl genrsa -out /etc/httpd/ssl/httpd.key 2048)
openssl req -new -key httpd.key -out httpd.csr -days 365 //需要指定私鑰-key
csr:證書簽署請求
信息要保證和CA的一致否則,可能會出錯
Common Name:hostname //必須與客戶端訪問時的名字一直,否則證書驗證不會通過,可以使用ip
A challenge password://測試可以留空
2.scp httpd.csr [email protected]:/tmp
拷貝到CA
3.openssl ca -in httpd.csr -out /etc/pki/CA/certs/httpd.crt -days 365
server簽證
cd /etc/pki/CA/
cat index.txt //文件會增加一行內容
serial //會變成 02
scp /etc/pki/CA/certs/httpd.crt [email protected]:/etc/httpd/ssl/
httpd.csr已經沒有用了
註意:只有自建CA的時候才用到/etc/pki/CA目錄,CA的請求者,是不需要把私鑰放在這個目錄中的
八、證書簽署案例
1.用到證書的主機生成證書簽署請求
mkdir /etc/httpd/ssl
cd /etc/httpd/ssl
(umask 077;openssl genrsa -out httpd.key 2048)
2.生成證書請求
openssl req -new -key httpd.key -out httpd.csr -days 365
3.將請求,通過可靠方式發送給ca主機
scp
4.在CA主機上簽署主機
opnessl ca -in httpd.csr -out /etc/pki/certs/httpd.crt -days 365

查看證書的信息
openssh x509 -in httpd.crt -noout -serial -subject //只看serial和subject
//可以使用-a

吊銷證書:

    步驟(在CA上執行)
        1.客戶端獲取要吊銷的證書的serial
            openssh x509 -in httpd.crt -noout -serial -subject
        2.CA吊銷證書
            先根據客戶端提交的serial和subject信息,對比其與主機數據庫index.txt中存儲的是否一致
            openssl ca -revoke /etc/pki/CA/newcerts/SERIAK.pem
            
            certs/httpd.crt  和 newcerts/01.pem有對應關系
        3.生成證書吊銷編號(第一次吊銷證書時執行) //哪怕第二次吊銷的是其他的證書都不再需要做的
            echo 01 > /etc/pki/crlnumber 
        4.更新證書吊銷列表
            openssl ca -gencrl -out thisca.crl
            查看crl
            opnssl crl -in /paht/to/crl_file -noout -text
    //到吊銷ca級別的時候,將會使用openca而不是openssl


openssl 指定文件,取出隨機數


小結:
1.genrsa生成私鑰,rsa提取公鑰,req用於自簽和他簽
證書查看:

    openssl x509部分命令
    打印出證書的內容:
    openssl x509 -in cert.pem -noout -text
    打印出證書的系列號
    openssl x509 -in cert.pem -noout -serial
    打印出證書的擁有者名字
    openssl x509 -in cert.pem -noout -subject
    以RFC2253規定的格式打印出證書的擁有者名字
    openssl x509 -in cert.pem -noout -subject -nameopt RFC2253
    在支持UTF8的終端一行過打印出證書的擁有者名字
    openssl x509 -in cert.pem -noout -subject -nameopt oneline -nameopt -escmsb
    打印出證書的MD5特征參數
    openssl x509 -in cert.pem -noout -fingerprint
    打印出證書的SHA特征參數
    openssl x509 -sha1 -in cert.pem -noout -fingerprint
    把PEM格式的證書轉化成DER格式
    openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
    把一個證書轉化成CSR
    openssl x509 -x509toreq -in cert.pem -out req.pem -signkey key.pem
    給一個CSR進行處理,頒發字簽名證書,增加CA擴展項
    openssl x509 -req -in careq.pem -extfile openssl.cnf -extensions v3_ca -signkey key.pem -out


本文出自 “黑馬騰空” 博客,請務必保留此出處http://hmtk520.blog.51cto.com/12595610/1983793

openssl加解密原理