美文网首页Ovirt程序员
【Ovirt 笔记】管理员登录密码的加解密实现分析与整理

【Ovirt 笔记】管理员登录密码的加解密实现分析与整理

作者: 58bc06151329 | 来源:发表于2018-02-26 17:39 被阅读57次

    文前说明

    作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

    本文仅供学习交流使用,侵权必删。
    不用于商业目的,转载请注明出处。

    分析整理的版本为 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) 变量中。
    • 私钥和公钥的内容每一次引擎安装都会发生改变。

    相关文章

      网友评论

        本文标题:【Ovirt 笔记】管理员登录密码的加解密实现分析与整理

        本文链接:https://www.haomeiwen.com/subject/nplyxftx.html