文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。
分析整理的版本为 Ovirt 3.4.5 版本。
- 管理员登录密码采用了 RSA 算法进行加解密。
- 主要使用了 EngineEncryptionUtils 工具类进行加解密操作。
1. 登录密码的加密
public static String encrypt(String source) throws GeneralSecurityException {
if (source == null || source.trim().length() == 0) {
return source;
}
else {
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, getCertificate().getPublicKey());
return new Base64(0).encodeToString(
rsa.doFinal(source.trim().getBytes(Charset.forName("UTF-8")))
);
}
}
2. 登录密码的解密
public static String decrypt(String source) throws GeneralSecurityException {
if (source == null || source.trim().length() == 0) {
return source;
}
else {
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE, getPrivateKeyEntry().getPrivateKey());
return new String(
rsa.doFinal(new Base64().decode(source)),
Charset.forName("UTF-8")
);
}
}
- 管理员登录密码采用了公钥加密,私钥解密的方式。
- 公钥和私钥都保存在了证书里面。
3. 证书的生成
- 证书相关配置信息保存在 /etc/ovirt-engine/engine.conf.d/10-setup-pki.conf 文件中。
[root@localhost ~]# cat /etc/ovirt-engine/engine.conf.d/10-setup-pki.conf
ENGINE_PKI="/etc/pki/ovirt-engine"
ENGINE_PKI_CA="/etc/pki/ovirt-engine/ca.pem"
ENGINE_PKI_ENGINE_CERT="/etc/pki/ovirt-engine/certs/engine.cer"
ENGINE_PKI_TRUST_STORE="/etc/pki/ovirt-engine/.truststore"
ENGINE_PKI_TRUST_STORE_PASSWORD="mypass"
ENGINE_PKI_ENGINE_STORE="/etc/pki/ovirt-engine/keys/engine.p12"
ENGINE_PKI_ENGINE_STORE_PASSWORD="mypass"
ENGINE_PKI_ENGINE_STORE_ALIAS="1
- 密钥库所在为 /etc/pki/ovirt-engine/keys/engine.p12。
- 从该密钥库中获取公钥和私钥。
public static Certificate getCertificate() {
return getPrivateKeyEntry().getCertificate();
}
public static KeyStore.PrivateKeyEntry getPrivateKeyEntry() {
try {
KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)getKeyStore().getEntry(
keystoreAlias,
keystorePassword
);
if (entry == null) {
throw new RuntimeException("Alias was not found");
}
return entry;
}
catch (Exception e) {
throw new RuntimeException(
String.format(
"Failed to locate key '%1$s'",
keystoreAlias
),
e
);
}
}
public static KeyStore getKeyStore() {
return _getKeyStore("PKCS12", keystoreFile, keystorePassword.getPassword());
}
keystoreFile = config.getPKIEngineStore().getAbsoluteFile();
public File getPKIEngineStore() {
return getFile("ENGINE_PKI_ENGINE_STORE");
}
3.1 engine.p12 密钥库的生成
- engine-setup 命令过程中,会进行 ca 的创建。
- 执行了 /usr/share/ovirt-engine/setup/plugins/ovirt-engine-setup/ovirt-engine/pki/ca.py
3.1.1 CA 证书的生成
- 在 ca.py 脚本中运行了创建登记的 shell 脚本 pki-create-ca.sh
self.execute(
args=(
osetupcons.FileLocations.OVIRT_ENGINE_PKI_CA_CREATE,
'--subject=/C=%s/O=%s/CN=%s.%s' % (
self._subjectComponentEscape(
self.environment[osetupcons.PKIEnv.COUNTRY],
),
self._subjectComponentEscape(
self.environment[osetupcons.PKIEnv.ORG],
),
self._subjectComponentEscape(
self.environment[
osetupcons.ConfigEnv.FQDN
][:MAX_HOST_FQDN_LEN],
),
random.randint(10000, 99999),
),
'--keystore-password=%s' % (
self.environment[osetupcons.PKIEnv.STORE_PASS],
),
),
envAppend={
'JAVA_HOME': self.environment[
osetupcons.ConfigEnv.JAVA_HOME
],
},
)
- 在 /usr/share/ovirt-engine/setup/ovirt_engine_setup/constants.py 中进行了 OVIRT_ENGINE_PKI_CA_CREATE 执行脚本名称的定义。
OVIRT_ENGINE_PKI_CA_CREATE = os.path.join(
OVIRT_ENGINE_BINDIR,
'pki-create-ca.sh',
)
- pki-create-ca.sh 中使用了 openssl 命令生成证书。
- 生成一个 2048 位的 RSA 私钥文件 /etc/pki/ovirt-engine/private/ca.pem。
openssl genrsa \
-out "${PKIDIR}/private/ca.pem" \
2048 \
|| die "Cannot generate CA key"
- 利用 RSA 私钥文件创建一个自签署的 CA 证书 /etc/pki/ovirt-engine/requests/ca.csr。
openssl req \
-batch \
-config "${PKIDIR}/cacert.conf" \
-new \
-key "${PKIDIR}/private/ca.pem" \
-out "${PKIDIR}/requests/ca.csr" \
-subj "/" \
|| die "Cannot generate CA request"
- 利用 CA 证书签署请求证书 /etc/pki/ovirt-engine/ca.pem
openssl ca \
-batch \
-config openssl.conf \
-extfile cacert.conf \
-extensions v3_ca \
-in requests/ca.csr \
-out ca.pem \
-keyfile private/ca.pem \
-selfsign \
-subj "${subject}" \
-days 3650 \
-startdate "$(date --utc --date "now -1 days" +"%y%m%d%H%M%S%z")"
3.1.2 engine 证书的生成
- 在 ca.py 脚本中运行了创建登记的 shell 脚本 pki-enroll-pkcs12.sh
for name in ('engine', 'apache', 'jboss'):
self.execute(
(
osetupcons.FileLocations.OVIRT_ENGINE_PKI_CA_ENROLL,
'--name=%s' % name,
'--password=%s' % (
self.environment[osetupcons.PKIEnv.STORE_PASS],
),
'--subject=/C=%s/O=%s/CN=%s' % (
self._subjectComponentEscape(
self.environment[osetupcons.PKIEnv.COUNTRY],
),
self._subjectComponentEscape(
self.environment[osetupcons.PKIEnv.ORG],
),
self._subjectComponentEscape(
self.environment[osetupcons.ConfigEnv.FQDN],
),
),
),
)
- 在 /usr/share/ovirt-engine/setup/ovirt_engine_setup/constants.py 中进行了 OVIRT_ENGINE_PKI_CA_ENROLL 执行脚本名称的定义。
OVIRT_ENGINE_PKI_CA_ENROLL = os.path.join(
OVIRT_ENGINE_BINDIR,
'pki-enroll-pkcs12.sh',
)
- pki-enroll-pkcs12.sh 中使用了 openssl 命令生成证书。
- 生成一个 2048 位的 RSA 私钥文件,文件名称为 $(mktemp) 环境变量。
- 采用了 3DES 加密。
- 密钥为 mypass 变量 DEFAULT_PKI_STORE_PASS 获取。
openssl \
genrsa \
-out "${TMPKEY}" \
-passout "pass:${pass}" \
-des3 \
2048 \
|| die "Cannot create certificate request"
- $(mktemp) 每一次 engine-setup 会改变。
[root@localhost ~]# echo $(mktemp)
/tmp/tmp.cxiEzfmSJd
- 利用 RSA 私钥文件创建一个自签署的 CA 证书 /etc/pki/ovirt-engine/requests/engine.req。
openssl \
req \
-new \
-days 365 \
-key "${TMPKEY}" \
-out "${req}" \
-passin "pass:${pass}" \
-passout "pass:${pass}" \
-batch \
-subj "/" \
|| die "Cannot create certificate request"
- pki-enroll-pkcs12.sh 中执行了 pki-enroll-request.sh 脚本。
"${BINDIR}/pki-enroll-request.sh" \
--name="${name}" \
--subject="${subj}" \
|| die "Cannot sign request"
- 利用 CA 证书签署请求证书 /etc/pki/ovirt-engine/engine.cer
openssl ca \
-batch \
-policy policy_match \
-config openssl.conf \
-cert ca.pem \
-keyfile private/ca.pem \
-days "${days}" \
-in "${req}" \
-out "${cert}" \
-startdate "$(date --utc --date "now -1 days" +"%y%m%d%H%M%S%z")" \
${subject:+-subj "${subject}"} \
${EXTRA_COMMAND} \
|| die "Cannot sign certificate"
chmod a+r "${cert}" || die "Cannot set certificate permissions"
3.1.3 最终生成密钥库
- pki-enroll-pkcs12.sh 中执行最终密钥库的生成 /etc/pki/ovirt-engine/engine.p12。
touch "${pkcs12}"
chmod go-rwx "${pkcs12}" || die "Cannot set PKCS#12 permissions"
openssl \
pkcs12 \
-export \
-in "${cert}" \
-inkey "${TMPKEY}" \
-out "${pkcs12}" \
-passin "pass:${pass}" \
-passout "pass:${pass}" \
|| die "Cannot create PKCS#12"
- 私钥文件名称每一次引擎安装都会发生改变,并且存放在 $(mktemp) 变量中。
- 私钥和公钥的内容每一次引擎安装都会发生改变。
网友评论