对称加密算法
非对称加密算法
非对称加密:加密密钥与解密密钥成对出现,一般为私钥和公钥。私钥用于签名或加密;公钥用于验签或解密。
RSA
密钥生成
- OpenSSL明文生成命令如下:
## generate private key without password
openssl genrsa -out rsa.key 2048
## export public key
openssl rsa -in rsa.key -pubout -out rsa.pub
- 明文私钥内容如下:BEGIN RSA PRIVATE KEY为PKCS#1格式
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEArzMYu9B07EwgLma0c+BK+vGAGrVqvRnhxPr4o7NVAfCqKe6V
7evym0ClkCK4NJ7s8bHJjmTxBXIpZuPOJBJhG2H0EALFap7sfzSxbbHIUkoJDO/c
kuo7enZ/R5UIs/esuua5/oiPlx3XY/9+OHviuyCtCPy0dFi7j9TNxstsUj7eXs+Y
r1TC+bA7CointNqi9TDwU3cM74jdgUrIU/uLtqL2mB22RCa80FfcURp7tQYVDyPO
nHex4ijjjyl1zi26YI1kxZf8dRlRoFfGTayrS/8Txp0KqGKEsLJyYQ8DeuEhW9gW
/Ka340ZC7ObVMqTzMJ7pzxyWmbRqHOIlO54jxQIDAQABAoIBAB2gHEyWAU97x+1Q
vK7jfIpWj/z0NGppl/3BGo5D4toDIiMZDw0+WrXaBqUK2e87+IEeOSD0/LSZC1s0
pkT/PqBsveJ/NXbEDOWtuVr9NwyDLGidnsTRCuG4a+lk0CXueazZGxZpbS52g1eL
eoJ+oGZYLipY4QLThlPZ/jnhaB238CfAQ+KfkkxdJcPEJWzONalWsTrb0RK+0WHZ
sgwJwCn9zBECZYNkHKKV0G1/TOyslZTZwo8aXCsEtwQmtwqtuYEaPCTrJ8YPpjoD
HjEdt6sUcCJd98aHxJ9zuABgDlq7NZAsAhgmdPPcnXu5xSFgFw7yPj/6UDgZxtcb
5VkSMsECgYEA2a9nKL241eMnqJ9/dBE84fNFEg0C9hNEljGr8sxilg0cs3nk4v6P
GRVcl6fjmRm6bIUzHPmFFFBOzr9JIlKv71II1S1Dn4l0gIuT5epPB1OlinBCU+Ur
jjhuZ3UOeZQ3LF9nKeDqn6jDjY6jXCQRK9xqKmzZ2yCUGrwYKpa0JskCgYEAzgla
B+y5bWPLYC0sv76yz5I+yTfIl7PAO6clgzSgBhHNFkjPA0eWcA/AA9tZS5Nz5MB5
ACiKN82dmnOedkkpJg29CTc7KttNTie5A7n+reKKV8qMMSM7I/MbQn/j7GIrW/uG
6WiZveXtK7o4jLZOGPE2nTx0iFGrrUjLK3TURx0CgYAdD3J5GOLNAvcvZqOQLiDv
lRdacow7p5TXbCglUK20lGmJeDNbLlqSIazrvgj/TlT52cpaCuF+Nb5fkV/FCj7c
dxogw1ssuB/qbTfAUMheFQebdKMWKhjncpcijpjxGB1Jei7+gz0vNUtt4WXjjhkQ
vusZYNCwlSfQbd3YCahhKQKBgC/xeSOy8AsGV8LPgEQ2CcHHVBjahDDYwPigklgP
nNUMu15eHt2ygM0evR2oowS1ERi/uOhShqcpj2zrTopTx+F0/PHyCjCUy05Oa/z0
ANFRj8OR/EFK424gGc3FmLHevhwvUVtq3auUnzW3pYUIvu+K4ZyA/tThvEMcVzqL
ewH5AoGBAKx3QRwdnCYFZTV26DO1LqjT3b2AbGBtM18u2mPwf593qJt3oJdJMGii
LGkGNZgCm88gMN/sY+chSJumlCHToFHLiovVIManpkv0Y7sXHw6TUeSjg5hB84b6
If/YzYcoFIpi1uKGVMSTnEdzLx1sjqM00qsVZz9cz8f71TMOOsQx
-----END RSA PRIVATE KEY-----
- 公钥内容如下:BEGIN PUBLIC KEY为PKCS#8格式
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArzMYu9B07EwgLma0c+BK
+vGAGrVqvRnhxPr4o7NVAfCqKe6V7evym0ClkCK4NJ7s8bHJjmTxBXIpZuPOJBJh
G2H0EALFap7sfzSxbbHIUkoJDO/ckuo7enZ/R5UIs/esuua5/oiPlx3XY/9+OHvi
uyCtCPy0dFi7j9TNxstsUj7eXs+Yr1TC+bA7CointNqi9TDwU3cM74jdgUrIU/uL
tqL2mB22RCa80FfcURp7tQYVDyPOnHex4ijjjyl1zi26YI1kxZf8dRlRoFfGTayr
S/8Txp0KqGKEsLJyYQ8DeuEhW9gW/Ka340ZC7ObVMqTzMJ7pzxyWmbRqHOIlO54j
xQIDAQAB
-----END PUBLIC KEY-----
- OpenSSL密文生成命令如下:
## generate rsa private key with password
openssl genrsa -aes256 -out name_private.key 2048
- 密文如下:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,6BD39B13ECA6BE46F418ECC341EEC626
p4TtCgJUP7Ik/f2xqJrJ3zfbGiA49T3Vrf9naKSYrZawGVhqYxRu+fiXePxKc25L
8rdnwCiF7x2xtR9uNWcWlFIe76KlPqrFMqBzVrEloOb0bM9TvZ06ZsYE6DrlH2xj
1NLzKz9I3CQ9M/VZIHInzvm7J1vFPFwSH5NSjq3oIVnMgfPMzaq5DCBYIxJ4nOEm
fGRx9bXnTzpIPCR6MrgmZiWzEt3akgkKSzQlfEEOLWfjEDBvJmuLO20CIfj+Q8Y6
rTMroud7sZb+FFDHAB3BolEp2Bqfi0YQJ8rMKTl+On3QFdBQD+v9jcTurqhD1C47
3KHieg18ZN2OxNTHHJMo0A1VEent6lvBSHIPKtgyUBP87+nUPsWoBDQV+zoL3pCP
O4zlY35WEt6BU+ImupkNNjZ70Sgfr3hUdXN3ZZi2rWUqGABzUpBREF9UuQVuqOeO
lpswWKMKQIXuvbZ70OdZ6JsUBMdeEIZSvEDeez85ef2GwuB6IvJtxmWNf4POiJxJ
oNponrYCh6RatQLDKgg0iqE2fkyq6QoKN8mFIHNwG7LS5CsSCiNzsj1lhl4pm2eB
5NQrInKa/sDFN1uFmtrWGw1bhyJdUPGPhaw5Xb1DRh1dbxooieEaCysuu+RpZpqc
AVwhrKf2IB2N82mEiQfD0FwJ4FGtBhlAmtMHHjtlDmbh1qzOYs1wUKpPY8C72fza
XwfS8kMdac3HWJc4osJ+/YoQv9cQtQX/DwiA/86nxRiogjbtDYERneu2ucxnzFrV
i0l9frX2qvkuXWArlT9+0zFZA3fTF0fP5j2mrf8tdTE+OdAVqRW50l2JiVId8qUv
2D5ygiHn1h+zPreeckA1386HMYwPirHcr/JpzrI5R+hCgXGEVi2GQISRjsVa2sqS
hNEirQFe7M6HPgtPaXcjKm/R8MY2aVHI3irTccXvIjDo2GCb85ZQFLqdQOE3N+h7
xrdcDaNZV6K6ZcudUsLiiH6gjXeiTL9VeSJQdyJ5mDJpEl9297JU7CbrRwndUgTV
qJ6Q5s9r158Bb0aLQwYFx0FEwqIiQB+tZoJ1e9+H8jNuRvDn35thMrOw+QcsMsT8
7QHL741jjcB51610afi5Zb2xhUKiWwrJLLKfp+e+4B3aFnhBm8anRcwBaYaF4OWK
4O8vialNxUelI6qJqyjb9sS/9G+YCmWjkvO/Wc7CcZ2dag0cxvyV+XZllUfFaZpN
5KbIH+zv+6pa2GyeePWekvsYQstXB43lKDYYjcO89SVGwEXGw1W7TlJI9SPZl3eR
FcN/O7CEcZfA17XDsS7u6FZgLfRlLeqSpRhRxgAuB7XpdwKVazPc6fVr48h6rH/M
Po9+wDUId7wrdAnxZgETpcIVgISpszfCYGKuYc1tZXaBDZxivHCV4oTdDp9uFwF1
QB6kZIcQ2evqDLtQt5jRNHl7792RNiwWIZd66WTV2fie2YHoF42lhj7/AdbI+nDx
Wzt0bvV5/lwsrnSZbLLTGwdxs/eoDrhhuCBeChoeXsxwm0yCu7cy8Ogqv/LXu5m8
Nm7HkkZ0eldHiFhOiRSDRCfzJwCBmZt6wPnvgsslBwYA8MCN5qI2a3nxMz5rxip/
-----END RSA PRIVATE KEY-----
- 其他命令
## view the public key
openssl rsa -pubin -in name.pub -noout -text
## remove the password of the private key
openssl rsa -in name.key -out name_plain.key
## view private key with interactive mode
openssl rsa -in name.key -noout -text
## view private key with a password file
openssl rsa -in name.key -noout -text -passin file:path/to/password
密钥分析
OpenSSL命令生成的私钥格式默认为PEM,所以在进一步分析私钥之前,先大致了解一些术语。
- PEM
- DER
- PKCS#1
- PKCS#8
PKCS#1
RSA的PKCS#1格式的私钥结构如下:其中比较重要的都是与RSA算法相关的整数,RSA算法细节不在此文讨论。
RSAPrivateKey ::= SEQUENCE {
version Version, //版本
modulus INTEGER, // RSA合数模 n
publicExponent INTEGER, //RSA公开幂 e
privateExponent INTEGER, //RSA私有幂 d
prime1 INTEGER, //n的素数因子p
prime2 INTEGER, //n的素数因子q
exponent1 INTEGER, //值 d mod (p-1)
exponent2 INTEGER, //值 d mod (q-1)
coefficient INTEGER, //CRT系数 (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
首先,我们可以通过以下Go代码将PEM格式的私钥转换为DER格式的字节串,并解析为可用于分析的私钥结构体:
func getPrivKey(keyFile string) (*rsa.PrivateKey, error) {
key, err := ioutil.ReadFile(keyFile)
if err != nil {
return nil, err
}
block, _ := pem.Decode([]byte(key))
if block == nil {
return nil, fmt.Errorf("failed to decode pem data")
}
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
fmt.Println(priKey.N.Bytes()) // 模数N
eBytes := make([]byte, 8)
binary.BigEndian.PutUint64(eBytes, uint64(priKey.E)) // 公有幂,一般为65537
fmt.Println(eBytes)
fmt.Println(priKey.D.Bytes()) // 私有幂
fmt.Println(priKey.Primes[0].Bytes()) // n的素数因子p
fmt.Println(priKey.Primes[0].Bytes()) // n的素数因子q
fmt.Println(priKey.Precomputed.Dp.Bytes()) //值 d mod (p-1)
fmt.Println(priKey.Precomputed.Dq.Bytes()) //值 d mod (q-1)
fmt.Println(priKey.Precomputed.Qinv.Bytes()) // CRT系数 (inverse of q) mod p
return priKey, nil
}
或者也可以通过ASN.1 JS Decoder对DER进行分析,为了方便,我们直接采用第二种方式分析,如下:
其中,模数N部分如下,其他类似:
a. 02: tag
b. 82 – 81: 代表长度用1byte表示,82代表长度用2byte表示(此字节部分tag后不存在)
c. 0101: length 2bytes表示
d. 00: 在modulus数据前添加00,原因未知,请知情道友告知。
e. 模数N