当前位置: 首页 > news >正文

本地搭建linux服务器做网站网站建设包含的内容

本地搭建linux服务器做网站,网站建设包含的内容,营销网络怎么填写,青岛网站建设铭盛信息Req指令介绍 功能概述和指令格式 req指令一般来说应该是提供给证书申请用户的工具#xff0c;用来生成证书请求以便交给CA验证和签发证书。但是#xff0c;OpenSSL的req指令的功能远比这样的要求强大得多#xff0c;它不仅可以生成RSA密钥、DSA密钥#xff0c;以及将它们…Req指令介绍 功能概述和指令格式 req指令一般来说应该是提供给证书申请用户的工具用来生成证书请求以便交给CA验证和签发证书。但是OpenSSL的req指令的功能远比这样的要求强大得多它不仅可以生成RSA密钥、DSA密钥以及将它们封装成证书请求还可以对现有的证书请求进行签名验证、格式转换及信息修改等。下面将通过对req指令的各个参数的介绍来了解其全面的功能。首先来看看req指令的格式:eq指令的许多选项跟OpenSSL配置文件(默认为openslcnf)的证书请求部分是紧密相关的如果在指令中有些选项需要指定的参数没有给定那么req指令就会从配置文件中相应的字段去查找设置值。此外有相当部分的证书请求属性都是由配置文件的相关部分决定的。在本节的介绍中会指出相应的证书请求配置部分内容。  输入和输出格式选项informoutform和keyform inform选项指定了选项in指定的输入证书请求文件的编码格式目前来说支持的编码格式有两种:PEM编码和DER编码默认为PEM编码。in选项指定的文件输入内容是一个已经存在的符合PKCS#10标准的证书请求在这里输入的目的一般是为了验证和显示其中的一些内容。outform选项指定了输出选项out输出的证书请求或自签名证书的编码格式目前支持的编码格式包括PEM编码和DER编码默认为PEM编码。需要注意的是该选项指定的格式不影响keyout选项的密钥编码格式和pubkey输出的公钥编码格式。keyform选项指定了密钥输入选项key指定的密钥编码格式目前来说可以接受的编码格式包括PEM编码格式、DER编码格式、PKCS#12编码格式、Netscape编码格式、旧版本的IISSGC编码格式及Engine格式。 输入和输出文件选项inoutkey和keyout in选项指定了保存证书请求的文件名默认是标准输入。如果启用了该选项那么指令将根据一个已经存在的证书请求生成自签名根证书或者显示其中的一些内容但是该证书请求的内容基本上是不能进行变更的。如果是要根据现有的证书请求生成自签名根证书(使用x509选项)那么要求同时使用key选项指定证书请求里面的公钥相应的私钥以便对自签名根证书进行签名。如果使用了new选项或者newkey选项那么in选项指定的证书请求文件将被忽略。in选项输入的证书请求的编码可以是PEM格式也可以是DER格式由inform选项指定。out选项指定了输出文件名默认是标准输出。输出文件可以保存包括证书请求、自签名证书、编码公钥以及由text、subject、modulus等选项指定的明文输出信息。其中证书请求和自签名证书的输出编码格式可以为DER编码或者PEM编码由outform选项指定。公钥(如果使用了pubkey选项输出)的编码格式固定为PEM格式。key选项指定了输入私钥的文件该文件内的私钥编码格式由keyform指定。需要注意的是如果keyform指定的编码格式是ENGINE格式那么key指定的文件内容要根据具体的Engine接口而定可能是一个编码公钥也可能是一个字符串ID甚至可能是毫无意义的内容。密钥类型可以是RSA私钥也可以是DSA私钥。keyout选项指定了新生成的私钥的输出保存文件如果没有指定那么默认情况下会从OpenSSL配置文件中的req字段的default_keyfile选项的参数中获取输出私钥文件名(openssl.cnf文件默认值是privkey.pem)。仅在使用了newkey或new选项导致生成新密钥对的时候该选项才有效如果使用了已有的私钥(key选项指定)那么该选项就会被忽略。该选项输出的私钥编码格式固定为PEM编码。输出到keyout选项指定文件的私钥一般都会被加密保护加密的算法是DES3的CBC模式。 输入和输出口令选项passin和passout passin选项指定了读取key选项指定的私钥所需要的解密口令输入口令的方式可以是多样的。如果没有使用该选项而key选项指定的私钥又要求提供解密口令那么指令会在指令行提示用户输入口令。passout选项指定了使用keyout选项输出私钥时使用的加密口令。如果使用了nodes选项则表示不对私钥进行加密那么该选项指定的口令无效。如果该选项没有使用并且输出了私钥也没有使用nodes选项那么指令会要求用户从指令行界面输入加密口令。 指令操作类型newnewkeynodes和x509 new选项告诉指令执行生成新的证书请求操作这时候in选项指定的输入文件会被忽略。使用new选项后如果没有使用key选项指定私钥用于生成证书请求那么就会根据newkey选项的参数生成新的密钥对。默认情况下如果指令既没有使用key选项也没有使用newkey选项那么指令就会生成一个RSA密钥其长度由OpenSSL配置文件中req字段的default_bits选项的参数决定。newkey选项让指令生成一个新的密钥对该选项只有在没有使用key选项的时候才有效。newkey选项有两项功能:指定生成的密钥类型和密钥长度。newkey选项的参数有如下两种形式:rsa : numbitsdsa : file其中rsa代表生成RSA密钥作为证书请求的密钥对dsa则表示生成DSA密钥对作为证书请求的密钥对。numbits表示要生成RSA密钥的长度一般来说使用1024位作为普通证书请求是合适的。file是存储了DSA密钥参数的文件名DSA密钥的长度由该文件存储的DSA参数决定。nodes选项告诉指令不对新生成的私钥进行加密保存这样passout选项将被简单忽略。如果没有使用nodes选项并且生成了新的私钥那么私钥输出到keyout指定的文件中时将会被以DES3的CBC模式加密。x509选项让指令生成一个自签名根证书而不是输出一个证书请求。所谓自签名根证书就是指用一对密钥对的私钥对自己相应的公钥生成的证书请求进行签名而颁发证书这样证书申请人和签发人都是同一个所以称为自签名根证书。如果根证书不是用于根CA那么一般来说只有测试上的意义。在req指令中既可以直接生成一个新的自签名根证书也可以根据现有的证书请求和其相应私钥生成自签名根证书。如果是根据现有证书请求生成自签名根证书那么一定要key选项提供相应的私钥指令才能执行成功。 属性设置选项digestsubjdays和set_serial digest选项指定了生成证书请求或者自签名根证书时使用的信息摘要算法该信息摘要算法一般在生成数字签名的时候使用需要注意的是如果使用的是RSA算法理论上除了DSS数字签名标准指定的信息摘要算法(ds1)不能使用以外其他信息摘要算法都能够用于生成数字签名并且req指令也能够正确执行但是由于RIPEMD算法在标准中没有得到支持很可能导致某些CA和应用程序不能正确使用。如果使用的密钥是DSA密钥那么digest的任何设定都会被忽略事实上这时digest的值就固定为DSS规定的信息摘要算法。默认的digest算法是MD5。subj选项直接从指令行指定了证书请求的主体名称如果没有出示该选项那么req指令将会根据配置文件特征名称字段的设定提示用户输入必要的信息比如国家代号(通常是两个字符)、省份、单位名称等等。如果使用subj选项那么这些提示信息就不会再出现。subj选项的参数格式如下:参数应该以“/”开头每个值直接使用“/”作为分隔符号。“type* ”应该是OpenSSL内部支持的数据对象名称。比如下面是一个例子:days选项设定了生成的自签名根证书的有效期单位是天。该选项只有在使用了x509选项生成自签名根证书的时候才有效。默认值是30天。set_serial选项指定了生成的自签名根证书的序列号默认情况下生成的自签名根证书序列号是0。该选项也只有在生成自签名根证书的时候有效。  配置文件选项configextensions和reqexts config选项指定了req指令在生成证书请求的时候使用OpenSSL配置文件该文件的最好例子是openssl.cnf一般来说openssl.cnf也是默认的req指令配置文件。但是如果在Windows环境中使用并且在编译的时候没有指定正确的路径那么该默认配置文件很可能因为路径不正确而不能不到这时候使用config选项就显得非常必要了。当然config选项并非指定配置文件的唯一方法你还可以使用OPENSSL_CONF或者SSLEAY_CONF环境变量指定默认的配置文件extensions选项指定了生成自签名根证书的时候使用的扩展字段其参数为OpenSSL配置文件中某个字段名(比如opensl.cnf文件中的v3_ca字段)。该字段一般规定了一些证书的扩展项信息比如证书的用途是否能够作为CA证书等性质。reqexts选项指定了生成证书请求时使用的扩展字段该字段参数也是配置文件中的某个字段名比如openssl.cnf文件中的v3_req字段该字段也是证书请求中设置的要求申请的证书的一些使用限制信息。其内容跟证书扩展项内容基本一致。extensions选项和reqexts选项使得在同一个配置文件中可以存在多个不同的字段用于生成不同用途和目的的证书比如申请一个CA证书和用户证书的证书请求扩展字段设置是不一样的那么可以在配置文件中将两种不同的证书请求设置分别写成两个不同的字段在生成证书请求的时候根据需要使用reqexts选项指定不同的字段即可达到不同的目的。 属性格式化选项asn1-kludgenewhdr和utf8 一般情况下如果证书请求的某个属性没有填写那么对应的证书请求字段会填写一个空的值。但是某些不完全标准的CA不能正确处理这些空值它们的要求是:如果没有填写任何值那么该属性字段就不应该出现在证书请求中。对于这些CA你可能就需要使用asn1-kludge选项实现这个目的(与属性相对应的字段为空就不出现在证书请求中)。newhdr选项使用后将会在输出的PEM编码的证书请求开始和结束行增加“NEW”标记字符串这是为了跟Netscape和其他一些证书服务器兼容设置的选项。使用newhdr和不用newhdr选项的证书请求格式如下。utf8选项使用之后将对输入的信息采用UTF8编码而不是默认的ASCI编码。UTF8编码对于中文来说具有很重要的作用。 engine选项 engine选项指定后所有指定Engine支持的操作都将使用Engine指定的加密库或者硬件设备进行而不再是使用OpenSSL默认的算法库。对于req指令来说可能使用Engine设备的操作包括RSA或者DSA密钥产生、签名时使用的信息摘要算法、签名时使用的私钥加密算法、签名验证操作的公钥解密操作、随机数产生和对私钥进行加密的DES3算法。如果engine选项指定了有效的Engine设备那么指令中任何该Engine设备支持的上述操作都会使用Engine设备的操作流程而不再使用OpenSSL算法库本身提供的函数。 输出内容选项textreqoptpubkeynoout和subject text选项让指令输出证书请求或者自签名根证书内容的明文解析默认情况下它将输出所有可能输出的内容但是如果使用了reqopt选项其输出内容就取决于reqopt选项。reqopt选项用于指定text选项输出的内容其参数可以是多个每个之间使用“”作为连接符号。reqopt支持的参数如表所示。 对于证书请求来说上表中的很多内容没有对于这种情况指令会自然忽略相关的参数也就不会产生任何作用。reqopt选项只有在跟text选项一起使用的时候才有效。例如我们要使输出自签名证书的文本信息不包含序列号和公钥信息则可以使用下面的指令:pubkey选项使用后指令将会输出PEM编码的公钥到out选项指定的文件中。默认情况下只输出私钥到keyout指定的文件并不输出公钥。noout选项使用后指令将不会输出编码的证书请求或者自签名根证书到out选项指定的文件中该选项一般用来测试指令或者查看证书请求的信息。subject选项告诉指令输出主体名信息即使已经使用text选项输出了主体名信息该选项的启用也会让指令重复输出一遍主体名信息。 输出字符编码选项nameopt nameopt选项指定了如何显示主体名称和签发者名称主要用于显示名称中不同编码的内容比如UTF8编码等。如果没有使用该选项那么默认使用的是“oneline”参数。该选项可以同时使用多个参数每个参数之间使用“”作为连接符。此外每个参数之前还可以使用“-”表示不使用该参数定义的显示方式。如表所述是nameopt选项支持的所有参数。需要注意的是nameopt选项只影响使用text和subject选项输出的主体名称和签发者名称的显示方式对其他项目的显示方式没有影响。上述的功能对于正确显示中文信息来说具有很重要的意义。前面说过可以同时使用多个参数下面是一个例子: 上述指令指定在显示自签名证书的主体名称和签发者名称时使用单行显示方式但是禁止在显示之前进行UTF8格式的转换并且域名称使用长名称进行显示。  证书请求数字签名验证选项verify 使用verify选项的指令将对证书请求的数字签名进行验证操作并给出失败或者成功的提示信息。其验证的过程是从证书请求里面提取公钥然后使用该公钥对证书请求的数字签名进行验证。 其他选项randbatch和verbose rand选项指定了生成密钥对或者其他一些操作需要的随机数种子文件。如果没有使用rand选项指令会从其他可能得到的资源取得随机数种子数据。使用batch选项将不再提示用户输入生成证书请求需要的用户信息而是直接从OpenSSL配置文件特征名称字段读取默认值如果没有默认值则不填写该值域。一般来说在你做测试的时候使用该选项会提高效率。verbose选项让指令输出执行的各个操作的详细信息一般来说该选项也仅对调试程序有意义。生成证书密钥 证书请求中使用RSA密钥 RSA密钥是目前证书中最经常使用的密钥类型这一部分是因为其既可以支持密钥交换又可以支持数字签名的特性;更重要的是RSA算法是一种经过充分考验和密码分析的算法其安全性得到了公认。在使用req指令生成证书请求时我们可以采用两种方法生成RSA密钥对:一种是使用genrsa指令预先生成密钥对一种是直接在req指令中生成密钥对。从本质上来说这两种方法没有区别但是使用第一种方式能够更灵活地处理密钥的保存和格式等问题。我们首先看下面的指令它使用req指令直接生成了一个新的1024位RSA密钥用于新的证书请求中:上述指令对生成的RSA私钥进行了加密加密的算法自己是没有选择余地的只能是DES3-CBC模式当然你可以使用rsa指令对密钥使用的加密方法和口令进行重新的更改。此外私钥输出的编码格式也没有选择的余地只能是PEM编码。这些限制可能很多时候不能满足你的要求。为了避免上面这些限制你可以使用genrsa指令先生成需要的RSA密钥对然后再使用req指令生成证书请求。事实上在实际应用中你的RSA密钥对甚至可能不是使用OpenSSL的指令工具生成的但这没有关系只要你的密钥封装格式是req指令中keyform选项支持的那么就能够使用req指令生成证书请求。下面我们来看怎么使用genrsa指令和req指令生成一个证书请求。虽然说DES3-CBC方式的安全性一般还是值得信赖的但我们更愿意使用256位的AES算法保护我们的RSA私钥毕竟对于私钥来说怎么提高它的安全性都不为过。显然req指令满足不了我们的要求那么可以使用genrsa指令: 证书请求中使用DSA密钥 DSA密钥是专门用于数字签名的密钥当你要申请一个用于数字签名的证书的时候就可能需要使用这种类型的密钥。跟RSA密钥产生不同DSA密钥一般通过其预先生成的DSA密钥参数来生成DSA密钥。req指令提供了根据DSA密钥参数生成DSA密钥的功能而DSA密钥的长度则由给定的DSA密钥参数决定。当然你也可以根据给定的DSA密钥对生成证书请求。下面我们介绍利用req指令本身生成DSA密钥的功能。由于req指令要求输入一组DSA密钥参数来生成DSA密钥所以我们必须首先使用dsaparam指令生成DSA密钥参数。需要注意的是req指令只能接受PEM编码的DSA密钥参数。首先生成DSA密钥参数的指令如下:跟使用req指令生成RSA密钥对相同的是输出DSA私钥的加密算法只能是DES3-CBC模式编码方式也只能是PEM方式。所以为了灵活和方便你可能愿意使用gendsa指令来生成DSA密钥然后再使用req指令生成证书请求文件。首先我们利用刚才生成的DSA密钥参数文件生成一对DSA密钥:再次强调上面我们在生成RSA或者DSA密钥对的时候都只输出了私钥文件这是因为私钥文件结构中已经包含了相应的公钥参数req指令使用私钥的时候事实上主要是从其中提取出相应的公钥并封装在PKCS#10的证书请求结构中然后采用私钥对整个证书请求结构签名从而完成操作。 谁来生成密钥对 如果私钥由用户本地生成使用其公钥加密数据如果用户消失会给组织带来巨大的危险。考虑到这点为了方便管理通常就由CA或者RA来生成用户的密钥对并在发放证书的时候将证书和密钥对一起发送给用户。但这显然违背了私钥是唯一被主人拥有的假设这样你可能觉得非常没有安全感因为掌握备份密钥库的人可能随时可以查看你的任何资料和通信内容但是你没有任何办法。对于用于数字签名的证书来说情况会好一点因为数字签名不需要对整个文件进行加密它不存在数据恢复的问题。即便私钥丢失或者破坏了也只是不能使用它继续签名其他文件而已换一个就是了。所以用于数字签名的密钥对不需要备份功能一般可以由用户自己产生。从法律角度而不是保密角度来看数字签名的唯一性显得尤为重要。由于上述的这些原因现在很多系统都使用所谓双证书的概念即一个证书用于密钥交换一个证书用于数字签名。用于密钥交换的证书其密钥对一般由CA或者RA代替用户产生;而用于数字签名的证书的密钥对则由用户自己产生。事实上这样的做法只是在法律上得到了保证而数据保密性能则很值得怀疑尤其是个人的隐私问题。具体到技术上如果采用的是用户自身生成密钥对那么req指令的功能应该由用户来使用。但是如果是CA或者RA生成密钥对req指令跟用户基本就没有关系了事实上这时候req指令的功能应该由RA或者CA执行而用户只要简单地把自己的信息交给RA或者CA就可以了。但是CA真的那么值得信任? 在证书中添加扩展项 要真正用好req指令提供的功能仅仅了解req指令的选项和参数是不够的还需要对req指令所依赖的OpenSSL配置文件中的req指令相关字段有比较深入的了解。一下子要全部了解是不可能的使用OpenSSL配置文件中的证书请求相关字段实现一些扩展的功能。首先我们看看怎么在证书请求中增加一个自己定义的扩展项。在某些特殊情况下可能需要在证书中扩展一些标记以便实现一些特定的功能比如你可能需要在给你公司员工发放的证书中增加一项权限的功能这可能给会给管理带来很大的方便尤其对于有多个服务器的分布式系统中这种证书尤其有用。下面我们就通过往证书的特征名称字段中添加一个扩展的字段实现存取用户的权限信息。首先请打开OpenSSL默认的配置文件opensl.cnf然后确保其中的下列语句没有被注释掉:上面定义了一个新的OID对象其简短名称和长名称都是UserRights而OID则为2.5.4.255。下面我们就要在证书请求的特征名称字段添加我们新增加的这个OID对象使得证书主体名称中能够增加一项代表用户权限的值域。为了使得管理方便我们限定该项的值只能是两个字符默认的值是“US”(User)表示普通用户权限。下面是往req_distinguished_name字段添加的语句: 设置完上面这些内容我们就可以使用这个配置文件作为req指令的配置文件进行新证书请求的签发。你会发现在生成证书请求时提示输入信息中多了一项提示内容即“UserRights”选项用户就可以根据自己对不同权限的命名填写内容了。如果你用text选项则显示的证书请求主体名称形式如下:如果证书应用的系统是一个分布式的系统那么这些选项对于分布式的权限控制等会产生非常大的好处。当然要在最后生成的证书中增加这些扩展项CA的配置文件相应的一些选项也需要做一些更改  申请用户证书 证书按照其在证书链中的位置分类一般可以分为两种:终端用户证书和CA证书。所谓CA证书是指该证书可以用于签发别的用户证书也就是说它可以有下级的证书。终端用户证书则用于具体应用程序或协议中它不能用来签发别的证书在证书链中它处于最末端。对于一般用户来说申请的证书都是终端用户证书。对于生成证书请求的req指令来说生成的证书请求是用于申请一个终端用户证书还是CA证书是由OpenSSL配置文件的证书请求X.509v3扩展项字段来决定的opensl.cnf文件中的默认字段名是req_v3。为了使req_v3扩展字段生效首先必须确保配置文件req字段中的下面语句没有被注释掉:接着我们修改v3_req字段中的basicConstraints选项为下面的形式:然后保存利用这个配置文件作为req指令的配置文件其生成的证书请求就是一个申请终端用户证书的证书请求如果你使用text选项输出明文信息你会发现在“RequestedExtensions”部分出现下面的信息:上述的CA:FALSE值即表示该证书请求不是CA证书请求而是普通的终端用户证书请求。当然证书请求的这个扩展字段最后能起到什么作用还得取决于签发证书的CA的具体策略。生成一个CA证书请求而不是普通的终端用户证书请求修改如下然后保存利用这个配置文件作为req指令的配置文件其生成的证书请求就是一个申请CA证书的证书请求如果你使用text选项输出明文信息你会发现在“RequestedExtensions”部分出现下面的信息:上述的CA:TRUE值即表示该证书请求是CA证书请求。同样证书请求的这个扩展字段最后能起到什么作用还得取决于签发证书的上级CA的具体策略。 建立CA CA是集技术和管理于一体的庞大机构 CA服务器的基本功能 CA服务器是一个应用程序它从技术上实现了符合PKI和X.509等相关标准的证书签发和管理功能。总的来说其基本功能应该包括以下几个方面:接受申请证书的请求、审核证书请求、签发证书、发布证书、吊销证书、生成和发布证书吊销列表(CRL)及证书库的管理。 接受证书请求 这是首先必备的功能一个CA应用程序必须能够从各种途径接受用户的证书请求至少需要一个这样的途径和接口。一般来说证书请求的提交归纳起来有三种:在线实时提交、在线非实时提交和本地提交。在线实时提交是指提供一个应用接口(一般是个服务端口)用户可以通过支持CA服务器规定的证书请求协议发送证书请求信息CA服务器能够实时响应提交的请求并作出是否提交成功的回复如果CA服务器是自动签发证书并且你的申请符合设定的条件用户就有可能快速得到签发好的证书。这种方式的实现一般采用C/S的模式需要客户端软件的支持。在线非实时提交一般通过Web方式实现用户可以通过Web页面把证书请求提交到服务器指定的一个目录或者数据库中然后CA服务器程序或其管理员可以定期或者不定期检测数据库如果发现有新的证书请求则起动证书请求审核和签发流程。这种方式的实现一般采用B/S结构。本地提交方式即用户到CA服务器所在地或者RA服务器所在地提交或填写自己的资料和申请证书的请求然后交给CA服务器管理员处理。一般来说如果你的CA实现的是密钥对由用户自己生成的方式那么一般接受的证书请求都是符合PKCS#10标准的。如果不是这样即CA服务器号称可以替代用户生成“安全”的密钥对的方式那么接受的资料很可能就是一些文本资料至于具体的格式就根据自己的需要决定了。上述三种接受证书请求的模式各有其不同的应用环境。在线实时接受申请模式实现起来工作量会比较大并且需要客户端软件的支持;但是也有好处在某些必须使用数字证书的客户端软件中可以集成证书自动申请功能这样就简化了用户使用客户端软件时候的配置操作。而基于Web方式的在线非实时提交方式实现起来显然比较容易。本地提交方式能够提供对用户身份进行严格确认的机会这对于证书的安全应用能够提供很好的保障。 审核证书请求 很难说审核证书请求仅仅是一个技术上的问题事实上审核过程要求得更多的是管理的策略。当然你可以通过CA服务器程序将你的管理策略实现比如必须要求用户提交的证书请求中国家名称跟规定的相一致等等。当然仅仅这些是不够的严肃对待一个证书请求的态度是验证严格审核其各个条目的信息并在有必要的时候跟用户本人进行核实。这就至少要求CA服务器能够向管理员显示出一个证书请求的所有详细内容这就是CA服务器对审核证书请求的基本要求当然CA服务器可以实现 签发证书 如果通过了证书请求的审核过程那么签发证书就是CA服务器马上要执行的操作。该操作实际上是将证书请求的信息和CA服务器自己的部分信息按照X.509的标准进行格式化然后CA服务器使用自己的私钥对所有这些信息进行数字签名然后形成一个X.509标准的证书。接着当然要将证书保存在证书库中并对证书库进行更新。 发布证书 证书签发好后就需要将证书发布出去。发布对象有两种:一种是申请证书的用户本人必须让他能够及时获得自己的证书;一种是其他用户可以向他们提供获得所有用户证书的途径。一般来说可以通过Web方式或LDAP目录发布证书当然对于申请证书的用户本人也可以通过Mail或其他途径发送。在某些情况下比如是CA服务器生成证书密钥对的情况下还要考虑私钥的传输问题这一般来说需要高度考虑其安全性最好采用硬件设备来传送私钥。如果非要考虑用软件的方式来保存私钥那么一般需要对私钥进行加密保存最简单的方式就是将证书和私钥一起封装成PKCS#12的证书然后通过可能的途径发送给用户本人。 吊销证书 有些情况下需要取消一个没有过期的证书的有效性那么这就需要CA服务器执行吊销该证书的操作这是确保整个CA证书域安全性的必备条件。吊销证书的操作一般就是更新证书数据库发布新的CRL等目的就是为了尽可能让所有用户都知道该证书已经无效。 生成和发布CRL 虽然所有已经吊销的证书在CA有效的证书数据库中都已经不存在但是用户在很多时候并不能实时地访问和查询CA数据库当然也就不能就此终止所有基于证书的应用服务。这时候就需要利用CA服务器发布的证书吊销列表(CRL)来进行证书的验证。CA服务器必须能够定期更新和发布CRL以便用户能够获得准确的CRL信息。 证书库管理 CA服务器的证书库存储了CA签发的所有有效证书有时候甚至也包括无效的证书和证书相应的私钥这就要求CA服务器能够对证书进行有效的管理。例如对证书状态的更新无效和过期的证书应该删除或者做相应的标记状态等等. CA服务器的基本要素 要建立和运行一个CA服务器那么至少应该具备以下一些要素: 一个具备CA应用程序;一个CA证书和一个其相应的私钥可能是自签名的根证书也可能是向另一个CA申请的证书;证书数据库用于存储证书(有时候还包括私钥)。CA应用程序的选择有很多如果你不介意微软的神秘代码可能隐含的安全性问题那么可以用Windows系统的CA服务器程序。你还可以选择OpenCA提供的CA服务器当然它事实上就是OpenSSL的封装版本。CA证书和私钥的产生根据不同的应用而定如果你的CA服务器是自成体系并不需要一个上级CA的支持那么可以使用OpenSSL的req指令生成一个自签名根证书作为CA服务器的证书即可。如果你的CA服务器是上级CA的一个下级CA那么就需要生成一个CA证书请求并发送给上级CA然后等待上级CA签发你的CA证书。证书数据库的选择是多样的你可以使用任何像SQLServerOracle和MySql这样的数据库也可以使用自定义的文本数据库甚至可以使用特定的目录结构等。这需要根据自己的需要而定。如果你选择现有的CA应用程序你可能没有这么多选择比如OpenSSL的ca指令就仅仅使用文本数据库。具备了上述这些基本的要素你的CA服务器就可以启动并运行签发证书的服务了。 OpenSSL模拟CA服务器架构 默认的CA目录结构上面介绍了各种CA应用服务器本章节的目的只有一个:就是介绍基于OpenSSL的ca指令的证书服务器。当然并非仅仅想告诉你OpenSSL的CA服务器是如何配置和使用的而是希望通过上面的介绍让你深刻理解CA服务器的工作流程和操作过程。OpenSSL的ca指令是一个模拟的CA服务器程序它实现了CA服务器的基本功能。ca指令的正常运行依赖于一个目录结构和一个OpenSSL配置文件OpenSSL配置文件我们已经相对熟悉了本节主要对这个目录结构进行介绍。如图所示展现了整个CA目录的结构。图中粗线条框显示的是目录而细线条框显示的则是文件。图中certs和crl目录是使用ca.pl程序创建生成的目前来说ca指令并没有使用这两个目录可以忽略。newcerts目录存放新签发的证书文件证书文件名是序列号后缀名是pem即输出的证书默认都是PEM编码的。比如签发的证书如果其序列号是01那么其保存在newcerts目录的证书文件名就是“01.pem”。private目录目前仅对于存放CA证书相应的私钥文件有意义其默认私钥文件名为cakey.pem。每次使用CA指令如果没有指定特别的密钥那么就会使用该密钥签发证书。demoCA根目录下的cacert.pem文件就是PEM编码的CA证书文件里面保存了CA的证书。如果没有使用ca指令的选项指定别的证书文件那么每次使用ca指令签发证书的时候就使用该证书。demoCA根目录下的index.txt文件是ca指令相应的文本证书数据库index.txt文件保存了已经签发的证书的信息和状态。demoCA根目录下的serial文件是ca指令决定签发证书的序列号所依赖的文件其格式和内容请参考第6章相关内容。在使用ca指令签发证书后你还会发现在根目录下还会产生serial.old和index.txt.old文件这是上次签发证书时serial和index.txt文件的备份文件一般来说不用理会它们。OpenSSL配置文件 事实上上面所说的所有目录结构都是可以改变的它们都由OpenSSL配置文件的CA字段所决定让我们来看看默认的opensl.cnf文件的这些相关配置选项:  如果你愿意你可以通过更改上述这些选项的值来更改ca指令使用的目录结构和文件。事实上在使用ca指令时指定特定的OpenSSL配置文件也是必备的条件之一。为了方便起见本书后面的章节在介绍ca指令时都以默认的目录结构为准。 建立基于OpenSSL的CA服务器 手动创建一个CA目录结构 假设我们已经拥有了ca指令程序和配置文件为了使ca指令能够正确运行首先就是按前面介绍的CA目录结构的要求创建这样一个CA目录结构和相应的文件。如果你愿意自己来一步一步建立这么一个目录那么可以按照下面的步骤进行。 1 在opensl可执行程序(Windows下是opensl.exe)所在目录下创建一个名为“demoCA”的目录。2 在demoCA目录下创建newcertsprivatecrl和certs子目录。3 在demoCA目录下创建一个空的名为index.txt的文本文件。4 在demoCA目录下创建一个空的名为serial的文件用文本编辑器打开(vi或者记事本)在文件中填入01保存退出。5 将CA证书文件转换成PEM格式复制到demoCA根目录下并重新命名为cacert.pem。6 将CA私钥文件转换成PEM格式复制到demoCA/private目录下并重新命名为cakey.pem。经过上述两个步骤你就建立了一个ca程序能够使用的CA目录结构。如果你的CA使用上级CA签发的证书那么你可能需要将证书和私钥文件转换成PEM编码的格式以完成第5和第6步的配置。如果你使用的是自签名根证书那么可以使用下面的req指令生成一个自签名根证书和私钥:自动创建一个CA目录结构 手动创建一个CA目录的过程是很烦琐的OpenSSL开发者能够理解大家的这种心情提供了一个基于Perl的脚本帮助大家自动创建一个CA目录结构。前提是你正确安装了Perl软件。首先你将OpenSSL的apps目录下的ca.pl文件复制到你想要放置CA目录结构的目录。接着在指令行界面进入到ca.pl所在的目录运行下面的指令:证书配置文件选项confignameextensionsextfile和policy ca指令跟OpenSSL的配置文件关系非常紧密ca指令的证书请求值域匹配策略、扩展项参数及其他默认的参数设置都是依赖于OpenSSL配置文件的相关字段。ca指令除了会自动寻找和使用默认的OpenSSL配置文件和字段外还运行用户在指令中指定的配置文件及特定的字段。config选项指定将要使用的配置文件。在默认情况下如果不使用config选项ca指令首先会寻找环境变量OPENSSL_CONF或者SSLEAY_CONF定义的文件名如果这两个环境变量都没有定义那么就使用OpenSSL安装时默认的路径。这个默认的路径通常情况下是“/usr/local/sl/opensl.cnf”当然你可以在安装OpenSSL的时候使用configure脚本指令更改这个默认的安装目录。比如通常在Windows下编译完OpenSSL后可执行文件openssl.exe通常在目录out32dll下而其配置文件则在apps目录下为了在out32dll目录下能够正确使用OpenSSL的ca指令可以使用config选项:在默认的情况下ca指令使用的CA主配置字段由配置文件中ca字段的default_ca选项的参数值决定。其形式如: 当然某些情况下你可能想使用在同一配置文件下(由config选项指定或默认得到的配置文件值)另外一个字段作为CA的主配置字段那么name选项就可以实现你这个目的。name选项的参数是字段名比如上面的“CA_default”指定的字段名应该是已经在使用的配置文件中定义好了的。例如在下面的名为openssl.cnf的配置文件中定义了一个新的名为My_CA的CA主配置字段:policy选项让指令使用其参数指定的字段名作为签发证书请求时的匹配策略字段其参数是配置文件中定义的一个字段名称。事实上在OpenSSL提供的openssl.cnf文件中就已经定义了两个匹配策略字段:policy_match和policy_anything。默认情况下ca指令通过CA主配置字段的下列选项采用policy_match字段作为匹配策略:如果你不想更改openssl.cnf但想使用policy_anything字段作为匹配策略字段则可以使用下面的指令实现你的要求: 假设你的CA需要管理不同的用户群而每个用户群需要自己特定的匹配策略比如每个用户群组织名称都不同但是要求同一用户群的用户组织名称必须相同那么就可以在配置文件中预先定义不同的匹配策略字段然后根据具体用户使用不同的匹配策略字段来签发证书。policy选项在这种情况下可以大显身手。extensions和extfile两个选项用来选定签发证书时候使用的X.509v3扩展项定义字段。extensions的参数是字段名用来选定配置文件中用于定义X.509v3扩展项的特定字段默认的字段所在文件跟config选项选定的配置文件或者默认的配置文件是同一个文件。但是某些情况下你可能希望使用一个专用的文件用来保存X.509v3扩展项信息那么这时候可以使用extfile选项指定这个文件。如果仅仅使用了extfile选项指定额外的X.509v3扩展项配置文件而没有使用extensions选项那么具体使用extfile指定的文件中那个字段由默认配置文件中CA主配置字段的x509_extensions选项决定类似如下的格式:如果extensions和extfile两个选项都没有使用那么默认的情况下就会使用config选项指定或者默认配置文件的CA主配置字段中x509_extensions选项参数指定的字段。例如在opensl.cnf文件中指定的就是上面所描述的usr_cert字段。假设我们在my_con.fig.cnf文件中定义了一个X.509v3扩展项字段如下: 使用好extensions和extfile两个选项能够使ca指令的运用更加灵活。例如你管理的用户可能其证书用途各不相同这可以通过在X.509v3的扩展项中来定义。为了方便签发各种不同用途的证书如果你不使用extensions选项或许你需要不断烦琐地更改配置文件的X.509v3扩展项字段(默认是usr_cert)相信这样下去很快你就会产生辞职的想法。不过如果你会使用extensions选项事情就不一样了你可以根据需要预先编辑好几个不同的x509_v3扩展项字段然后根据签发证书的需要使用extensions和extfile选项选用不同的字段从而实现不同权限的证书的签发。需要注意的是如果你提供了有效的X.509v3扩展项字段(不管通过指令选项提供还是配置文件选项提供)即便字段是空的指令也会生成一个X.509v3版本的证书。但是如果没有提供有效的X.509v3扩展项那么就生成X.509v1证书。 输入和输出选项ininfilesout和outdir in选项的参数是一个可以包含路径的文件名该文件保存的应该是一个PEM编码的PKCS#10格式的证书请求。事实上in选项仅用于证书请求的输入而不能输入其他类型的内容也就是说如果你使用了in选项那么表示你要执行的操作就是签发一个证书。infiles选项的参数是一系列包含PEM编码证书请求的文件跟in选项唯一不同的是它可以一下子输入多个证书请求文件而不是一个。该选项总是作为指令的最后一个选项其后面的所有参数都被认为是证书请求文件。out选项指定了输出签发好的证书或者新生成的CRL的文件。此外如果没有使用notext选项那么证书的明文信息也会输出到out选项指定的文件中这在大多数Windows平台上会导致证书文件不能被正确解释解决的最简单办法是使用notext选项禁止这些明文信息的输出。不过在较新的Windows系统如WindowsServer2003这个问题得到了解决。out选项指定的文件中输出的证书或者CRL都是PEM编码的。outdir选项指定了新生成证书的输出目录在默认情况下新生成证书总是输出到newcerts目录并且是以序列号加“pem”后缀成为一个完整的证书文件名。这些证书都采用了PEM编码。如果使用outdir选项指定了新的目录那么新生成的证书文件就会输出到这个新指定的目录。需要注意的是不管out选项是否给出都不会对输出到outdir或者其默认目录的证书文件产生影响。 特殊的证书请求输入选项s_cert和spkac 前面介绍的两种证书请求的输入方式即使用in或者infiles选项。它们的区别是输入单个证书请求文件还是输入多个证书请求文件。而它们的共同点则是输入的都是PEM编码的符合PKCS#10标准的证书请求。OpenSSL还提供了其他两种输入证书请求的方法即ss_cert选项和spkac选项支持的方法。ss_cert选项允许用户输入一个自签名的证书作为申请证书的证书请求ca指令将会从这个自签名证书中提取用户信息和公钥用于签发最后的用户证书。也就是说你可以使用req指令生成一个自签名证书而不是证书请求然后用这个自签名证书来向上级CA提供信息申请你的证书。spkac选项允许用户输入一个SPKAC格式的文件作为申请证书请求的资料spkac是Netscape规定的一种格式该格式包含了一个签名的公钥和其他附加用户信息。需要注意的是使用spkac作为证书请求输入时输出的证书编码是DER格式而不是PEM格式的。 证书有效期选项 startdatedays和enddate这三个都是用来设置证书有效日期的选项分别是设置证书的生效时间、证书的到期时间及有效时间。startdate设置证书的生效时间其参数格式是“YYMMDDHHMMSSZ”每两位代表一个时间变量分别是“年月日时分秒”。比如要定义签发的证书生效时间是2003年9月10日12时24分36秒(格林威治时间)那么startdate选项的参数就应该为“030910122436Z”。证书生效时间除了可以在ca指令的startdate选项指定外也可以在配置文件的CA主配置字段的default_startdate选项指定其参数格式跟startdate选项参数格式一致。如果没有设置startdate选项也没有在配置文件中定义default_startdate选项那么证书生效时间就是签发证书的时间。days选项设置证书的有效天数。所谓有效天数也就是从证书生效的时间到证书到期的时间之间的天数。enddate选项的参数格式跟startdate选项一样用来设置证书的到期时间。同样你也可以通过配置文件CA主配置字段中的default_enddate选项设定证书到期时间。如果设置了enddate选项那么days选项将会被自动忽略。如果没有设置证书到期时间那么就会根据days选项设置的有效时间来决定证书到期时间。如果指令中也没有使用days选项那么指令就会从CA主配置字段读取default_days选项的参数来决定证书有效期。 证书内容选项subjpreserveDNnoemailDNmd和msie_hack 一般情况下签发证书的时候证书的主体名称(subjectname也称为特征名称)由证书请求中的主体名称决定。不过有时候用户自己填写的资料可能并不能让你这个挑剔的CA管理员满意那么你可以使用subj选项重新填写用户的证书主体名称。subj选项的参数格式应该如下:其中“type*”必须是已经由OpenSSL内部定义或者在配置文件中定义了的数据对象。preserveDN选项使指令在签发证书的时候让证书主体名称内的各项内容顺序跟证书请求中的顺序保持一致。而在默认情况下证书主体名称内的各个选项顺序是按照配置文件中的证书匹配策略字段的选项顺序进行排列的。这个选项对于老版本的IE证书管理器是必要的而现在则显得很不必要了。一般来说证书的主体名称里面可以包含E-mail项目但是因为E-mail可能是一个经常变动的项目所以如果不把它放在证书主体名称中而是放在主体别名中会更好一点。noemailDN选项可以帮你做到这一点当证书请求中有E-mail这一项但是你不希望在证书主体名称中出现E-mail时可以使用这个选项来去除。如果你还使用了证书主体别名并使用了“email:move”或者“email:copy”策略那么使用该选项后指令会自动将证书请求中的E-mail项目移动到证书主体别名中。缺少 md 和 msie_hack CA证书和私钥选项certkeyfilekeyformpassin和key 在签发证书的时候需要使用CA的证书和私钥对用户的证书请求进行签发证书操作。默认情况下证书和私钥文件都是通过配置文件的CA主配置字段的certificate和private_key两个选项决定的。不过OpenSSL的ca指令提供了cert和keyfile选项让用户能够选择另外的证书和私钥文件作为签发证书的CA证书和私钥文件。或许你很难想像这种特殊的需要为什么不使用预先设置好的证书和私钥文件呢?但是至少在测试的时候我们需要这些灵活的选项。事实上这些选项不仅仅可以用于测试因为CA的指令不仅仅用于签发证书还可以用于吊销证书和发布CRL某些时候发布CRL的角色跟CA的角色可以是不同的即需要使用不同的证书来完成证书签发工作和生成CRL的工作但是它们都使用同一个ca指令所以这些选项就能派上用场了。cert选项的参数是一个可以包括路径的文件名文件里面是一个PEM编码的X.509证书文件。keyfile选项的参数也是一个可以包括路径的文件名不过该文件里面可以包含的私钥格式就比证书文件丰富多了。目前来说支持的编码格式包括PEM编码格式、DER编码格式、PKCS#12编码格式、Netscape编码格式、旧版本的IISSGC编码格式及ENGINE格式。当然OpenSSL指令不能自动识别这些格式必须使用keyform选项指定某种具体的格式。pasin选项给定了读取私钥文件的时候需要提供的口令当然跟我们所熟悉的一样提供口令的方式可以是多样的比如从指令直接输入、从环境变量获取或者从文件获取等等。key选项是一个老选项其作用是直接从指令输入一个口令其功能可以被“-pasinpass:”选项所替代。 证书吊销选项revokecrl_reasoncrl_holdcrl_compromise和crl_CA_compromise revoke选项让你能够轻松地吊销一个证书其参数就是你需要吊销的证书文件名revoke选项吊销的证书应该是PEM编码的X.509证书。当然仅仅这样吊销可能还满足不了你的管理需求某些情况下你甚至希望告诉所有用户为什么要吊销这个证书以证明你是正确的。那么使用crl_reason选项吧crl_reason选项的参数是CRLv2版规定的一些吊销理由如表所示。上述的吊销参数对大小写是不敏感的。如果在吊销操作的时候使用了这些吊销参数那么生成的CRL就是v2版本的如果所有吊销证书操作都没有使用任何参数那么生成的CRL将是v1版本的。当你希望使用certificateHold码作为吊销一个证书的理由时还可以使用冻结指示代码扩展这可以通过使用crl_hold参数来添加。目前crl_hold支持的参数包括holdInstructionNoneholdInstructionCalIsuer和holdInstructionReject。crl_hold选项使用后设置证书吊销码为certificateHold并且用其参数设置冻结指示代码扩展项。crl_compromise选项使用后将证书吊销原因设定为keyCompromise其参数表示私钥泄密的时间。它的参数是符合“YYYYMMDDHHMMSSZ”格式的时间。其中“YYYY”代表4位的年份而其他位跟startdate选项的参数代表的意义一样的。crl_CA_compromise选项使用后将证书吊销原因设定为CACompromise其参数表示私钥泄密的时间。它的参数格式跟crl_compromise格式一致。上述的crl_reasoncrl_holdcrl_compromise和crl_CA_compromise只要同时使用一项即可如果同时使用了多项那么在指令中最靠后的一个将是有效的而前面的都视为无效。 CRL生成选项gencrlcrldayscrlhours和crlexts 执行完证书吊销操作后证书库中相应的证书记录会更新但是对于离线的应用验证程序而言还是没有办法知道被吊销的证书的序列号。为了让所有证书用户及时得到吊销证书的消息CA必须及时生成和发布CRL。gencrl选项用于生成一个CRL并将生成的CRL使用PEM编码输出到out选项指定的文件如果没有使用out选项则输出到标准输出设备。为了保证CRL能及时反映证书库的更新信息CRL也必须不断定期或者不定期更新最好的方法就是当发布一个CRL的时候同时限定该CRL的有效期那么到了有效期之后用户就必须下载新的CRL来使用。CRL更新的间隔时间可以根据需要选择如果是非常重要的证书应用系统并且用户数量比较大那么单位时间内执行吊销操作的可能性就大这时候可以将CRL的更新时间设置得短一点。反之如果系统用户数量不多证书应用系统的安全性也不是要求特别高那么更新时间可以设置得稍微长一点。crldays和crlhours选项跟gencrl选项一起使用以设置CRL的更新时间。默认情况下如果没有使用crldays选项或者crlhours选项指令会从配置文件的CA主配置字段的default_crl_days或者default_crl_hours选项读取默认值。crldays以“天”为单位设置CRL的有效期而crlhours则以小时为单位设置CRL有效期这两个选项可以一起使用比如你要设置CRL的有效期为5天12个小时那么可以设置crldays的参数为5而crlhours为12。crlexts指定了生成CRL的时候使用的扩展项定义字段其参数为字段名称。CRL扩展项字段是在OpenSSL配置文件中定义的。如果定义了CRL扩展项字段即便该字段是空的生成的CRL也将是v2版本的。如果没有提供CRL扩展项字段则将生成v1版的CRL。 证书管理选项status和updatedb status选项用来查看证书库中指定证书的状态比如是否有效、吊销或者过期等。该选项的参数是证书序列号。updatedb选项用来更新文本数据库的证书状态它主要用来更新证书库中已经过期的证书的状态信息。通常情况下即便证书已经过了有效期如果不使用这个选项OpenSSL的ca指令也不会自动更新证书库中相应证书条目的状态所以需要使用这个选 项来自动更新证书库的状态信息。 engine选项 engine选项告诉ca指令尽可能使用Engine设备提供的加密函数和算法替代OpenSSL本身的函数。对于ca指令来说可能替代的算法包括:签名时使用的信息摘要算法、签名时使用的私钥加密算法、验证证书请求中的数字签名时使用的公钥解密算法、随机数函数及私钥数据。engine选项对于使用硬件加密设备中的私钥作为CA的私钥具有重要的意义因为硬件中的私钥一般是不能导出的从而能够增加CA私钥的安全性。当然这需要相应Engine接口的支持。 notextbatch和verbose选项 使用ca指令签发完一个证书的时候你是不是经常发现大部分版本的Windows都不能正确解释你的PEM编码的证书文件?事实上这是因为OpenSSL的ca指令在签发证书的时候同时将证书的明文解析信息输出到了保存编码证书的文件前面从而导致这些不怎么标准的Windows程序解码失败(WindowsServer2003已经解决了这个问题)。解决这个问题很简单在签发证书的时候使用notext选项那么指令就不会输出明文信息到证书文件。使用batch选项后ca指令以批处理方式工作在这种方式下ca指令不提示用户输入任何信息而直接签发所有输入的证书请求。使用verbose选项将会输出更详细的一些操作过程信息 例子 在证书中添加扩展项 先前介绍了怎么在证书请求中增加自定义的扩展项。但是证书请求中增加了扩展项并不等于签发的证书就会自动增加扩展项。事实上从严格意义上说证书请求应该是用户生成的申请文件也就是说其所有内容基本上都是代表了用户的意愿并不能由此推断CA的策略。所以为了使证书中能够顺利增加扩展项信息我们还需要在CA指令的配置文件上做一些工作。你可能已经可以想像得到我们的证书扩展项工作同样需要在OpenSSL的配置文件中完成。首先请确认你已经在OpenSSL配置文件opensl.cnf中增加了扩展项的OID即以下信息:注意如果证书请求指令(req)使用的配置文件跟证书签发指令(ca)使用的配置文件不相同必须确保上面的信息在两个配置文件中都存在并且一致。下面找到配置文件中的CA策略配置字段如在openssl.cnf文件中是policy_match或者policy_anything字段在其中增加新增扩展项:当然跟其他DN字段信息一样新增扩展项的匹配策略也可以根据CA的需要调整为optional或者match等。完成上面的配置之后保存配置文件并使用该配置文件签发证书就可以生成增加了扩展项的证书。当然上述配置方法使得扩展项信息是增加在证书主体名称中的。 签发用户证书 先前介绍了怎么申请一个终端用户证书即怎么使用OpenSSL的req指令生成一个终端用户证书请求。同样签发什么类型的证书事实上是由CA决定的也就是说即便生成了一个有效的终端用户证书请求但是如果接受申请的CA不签发终端用户证书或者甚至因为错误配置导致签发了CA证书都是可能发生的。可以通过在OpenSSL配置文件中的X.509v3扩展项字段告诉ca指令签发用户证书。ca指令在使用默认的openssl.cnf作为配置文件的情况下使用的X.509v3扩展项字段是user_cert字段。在openssl.cnf文件中找到该字段确保basicConstraints选项的参数如下: 证明颁发的是终端证书当然默认情况下一般就是如此。使用该配置文件签发的证书就是一个终端用户证书。如果你使用的是自己定义的另外的X.509v3扩展字段那么也只需要保证上述的basicConstraints选项值为CA:FALSE就可以成功签发一个终端用户证书了。使用自定义的字段的方法就是在ca指令中使用extensions选项当然也可以通过修改配置文件中CA主配置字段的x509_extensions选项的值来实现。事实上当OpenSSL的ca指令使用默认的openssl.cnf作为配置文件的时候其签发的证书总是终端用户证书 签发下级CA证书 如果你正在为一个大型的跨区域企业或者政府部门建立一个CA系统那么你可能需要建立一个多级的CA体系这就涉及签发下级CA证书的问题。从技术上来说一个CA证书和一个用户证书并没有本质区别它们的数据项是基本相同的格式也是相同的一个下级CA证书的合法性也是通过上级CA的数字签名来保证和证明的。事实上区别普通终端用户证书和CA证书的唯一标记就是X.509v3扩展项字段中的选项basicConstraints。如果该选项值为CA:FALSE则表示证书是普通的终端用户证书;如果该选项值是CA:TRUE则表示该证书是CA证书。在OpenSSL的默认配置文件opensl.cnf文件中已经存在一个签发CA证书的X.509v3扩展字段v3_ca。将该字段的basicConstraints设置为如下格式:当然你还可以使用自己定义的X.509v3扩展项字段其使用方法是相同的。通过上面这些介绍你就可以使用OpenSSL的指令顺利签发一个下级CA证书从而建立整个证书域的分级管理对于大型的企业或者机构来说这非常方便  例子 建立多级CA 在完成这些步骤的整个过程中使用的OpenSSL指令只有req和ca两个并且参数形式基本是相同的。此外还需要配置OpenSSL的配置文件。 建立rootCA 建立RootCA技术上抽象的任务有三部分:建立一个CA目录结构、生成一个自签名根证书和修改配置文件。为了管理方便我们选定RootCA的根目录在C盘。首先在C盘根目录创建一个名为“RootCA”的目录。从编译好的OpenSSL目录中复制“openssl.exe”程序“opensl.cnf”和ca.pl文件到“C:\RootCA”目录下。打开Windows的指令行界面进入到“C:\RootCA”目录执行下面的指令:根据其提示步骤完成整个操作流程就可以成功在C:\RootCA目录下创建一个demoCA目录。执行ca.pl脚本指令的过程中会提示产生自签名的根证书可以忽略。下面我们使用req指令来生成一个使用2048位密钥的自签名根证书作为RootCA的证书。首先执行如下指令启动OpenSSL.exe程序进入OpenSSL的运行环境。 然后将文件rootca_cert.pem重命名为cacert.pem复制到“C:\RootCA\demo.CA”目录下取代原来的文件;将文件rootca_key.pem重命名为cakey.pem复制到“C:\RootCA\demoCA\private”目录下取代原来的同名文件。这就完成了RootCA证书和其相应私钥的设置。为了使RootCA能够同时签发普通用户证书和下级CA证书很多时候我们还需要对OpenSSL配置文件(C:\RootCA\opensl.cnf)进行一些配置但是由于OpenSSL默认的配置文件本身已经具有了两个不同的X.509v3扩展字段用于签发用户证书(usr_cert)和签发CA证书(v3_ca)所以在这里不需要再做更多的配置。当然在实际的应用中可能还需要对其他一些扩展项和匹配策略等配置信息进行修改。到此为止我们已经成功建立了一个RootCA是不是很简单? 建立SubCA SubCA是RootCA的下级CA它的证书的合法性需要由RootCA签名来证明。建立一个SubCA的简要步骤如下SubCA跟RootCA是两个不同的CA在实际情况下它们一般不在同一个计算机内运行但是大家都应该明白这里只是一个演示操作所以我们选定在C盘根目录下建立一个名为“SubCA”的目录作为SubCA的主目录。然后跟建立RootCA一样从编译好的OpenSSL目录中复制“opensl.exe”、“opensl.cnf”和ca.pl文件到C:\SubCA目录下。打开Windows的指令行界面进入到C:\SubCA目录执行下面的指令: 根据其提示步骤完成整个操作流程就可以成功在“C:\SubCA”目录下创建一个demoCA目录。这样SubCA的目录结构就建好了但是SubCA还没有合法的经过RootCA签名的证书和相应的密钥紧接下面的步骤就是完成这个任务。SubCA的证书跟普通证书是基本相同的除了其X.509v3扩展项的某些选项的限制有一些区别。首先为了向RootCA申请一个CA证书需要生成一个密钥对和证书请求。因为要申请的是一个CA证书所以证书请求的X.509v3扩展项跟普通证书请求有区别我们通过修改OpenSSL的配置文件来达到这一目的。用文本编辑器打开C:\SubCA\openssl.cnf文件修改其中v3_req字段的basicConstraints选项为下面的值: 这个指令生成了一个2048位的密钥对作为SubCA的密钥并同时生成了一个相应的证书请求。私钥保存在文件subca_key.pem中而证书请求保存在subca_req.pem中。为了获得合法的CA证书需要将证书请求提交给RootCA签发提交的途径是多样的可以通过网络连接提交也可以通过远程数据库提交而在这里我们只需要将subca_req.pem文件复制到C:\RootCA目录下就可以了。 上述的操作只是简单地使用新签发的证书和其相应私钥替换原来demoCA目录下的证书文件和私钥文件从而完成SubCA证书和私钥的设置。SubCA并没有下级的CA所以在OpenSSL配置文件中只要设定一个签发普通用户证书的X.509v3扩展字段即可。幸好OpenSSL默认的配置文件已经设置好我们不需要费神再去配置它。RootCA和SubCA都已经配置好了现在可以签发用户证书了。  签发用户证书A 结构显示用户证书A是RootCA签发的普通用户证书所以我们首先在指令行界面下到C:\RootCA目录下启动openssl.exe程序。生成一个用户证书事实上包含三个部分:生成密钥对、生成证书请求及签发证书。在这里我们使用req指令完成第一和第二个部分使用ca指令完成第三部分。普通用户证书的密钥对一般使用1024位密钥就可以了可使用下面的指令生成密钥对和证书请求:根据配置文件“C:\RootCA\opensl.cnf”的配置ca指令默认X.509v3扩展项使用的是用于签发普通用户证书的usr_cert字段所以我们执行下面的ca指令即可签发用户证书A:执行完上述指令后用户A就拥有了一个合法的RootCA签发的证书A和相应的私钥分别保存在C:\RootCA\userA_cert.pem和C:\RootCA\userA_key.pem文件中。  签发用户证书B 用户证书B的申请和签发跟用户证书A的申请和签发基本相同只是因为用户证书B是SubCA签发的证书所以应该在指令行界面下进入“C:\SubCA”目录并启动opensl.exe程序。然后执行下面的两条指令完成用户证书B的申请和签发:执行完上述两条指令用户B就拥有了一个合法的SubCA签发的证书B和相应的私钥分别保存在C:\SubCA\userB_cert.pem和C:\SubCA\userB_key.pem文件中。到此为止就完成了上述CA目录结构的构造任务。整个过程使用的指令非常简单只有req和ca两个。 证书使用 X.509证书 x509指令功能概述和格式 x509指令是一个功能强大的指令甚至超出了其名称所涉及的范围它既可以以各种方式显示一个证书的内容也可以对一个证书的格式进行各种有趣的转换甚至可以签发证书等。下面是x509指令的格式和选项:输入和输出格式选项informoutformkeyformCAform和CAkeyform inform选项指定了in选项所指定的输入文件的格式输入的文件可能是证书也可能是证书请求文件(当使用了req选项的时候)。无论哪种文件该选项可以接受的格式包括PEM、DER编码和老式的Netscape的编码格式。CAform跟inform参数的意义相类似不过它指定的是CA选项所指定的输入文件的格式。outform则指定了out选项输出的文件格式但是并非所有的内容都会受到这个选项的影响仅输出文件是证书或者证书请求文件的时候会受到该选项的影响。目前支持的格式同样包括PEM、DER和NET格式。keyform选项指定了signkey选项指定的输入私钥文件的格式支持PEM、DER和ENGINE三种格式其中ENGINE是指通过第三方驱动设备提供的私钥。CAkeyform的参数意义跟keyform相同不过它相关的文件是选项Cakey所指定的文件。 输入和输出选项inoutCA和CAkey in选项指定了输入的证书文件的路径如果使用了req选项则输入文件将被视为是一个证书请求文件而不是证书文件。文件的编码格式由inform参数决定。默认情况下输入是标准输入设备。out选项指定了接受输出的文件的路径默认情况下输出目标是标准输出设备。如果输出的是证书或者证书请求则其输出格式由outform参数决定。CA选项指定了在签发证书或者转换证书格式的时候需要的CA证书文件路径。其格式由CAform参数指定。CAkey选项则指定了签发证书或者转换证书格式的时候需要使用的CA证书相对应的私钥文件路径如果使用的私钥是Engine提供的则是一个Engine的索引文件如公钥文件等根据具体的Engine私钥索引方法具体决定。普通的私钥文件格式由CAkeyform参数决定。 输入口令选项passin passin参数给出了当使用signkey输入私钥文件时需要提供的口令字符串。在使用CA证书的私钥签发证书的时候则给出的是使用CAkey选项输入私钥文件时需要提供的口令字符串。一般来说signkey选项与CAkey选项是不会同时出现的。输入口令的方式可以是多样的。如果没有使用该选项而指定的私钥又要求提供解密口令那么指令会在指令行提示用户输入口令。 输出显示内容选项serialhashsubjectisueremailpurposemodulusfingerprintocspidstartdateenddatedatespubkeyC和nout 输出证书更加灵活的内容的选项text和certopt 使用text选项就可以看到证书的内容certopt选项可以帮助选择所需要的东西。certopt选项一般只有出现text选项的时候才使用它的参数值很多可以同时提供一个或者多个如果是多个它们之间要使用分号分开。certopt选项还可以在指令中多次使用这可以让你更随意地更改你的想法。certopt的参数具体意义详见表10.3但参数no_attributes在certopt选项中是无效的。  证书信任设置选项trustoutaddtrustclrtrustaddrejectclrejectsetalias和alias 这些选项都是对可信证书扩展字段进行设置的选项。事实上所谓的可信证书就是普通的证书加上一些扩展字段这些字段定义了该证书可以用来做什么和不能用来做什么并定义了证书的别名。一般来说在进行证书验证的过程中证书链中至少有一个证书应该是“可信证书”否则就不能完成验证过程。默认情况下必须在本地保存一个可信证书并且该可信证书应该是一个根CA证书这种情况下任何一个结束于该可信根CA的证书链上的证书可以用于指定用途。事实上现在OpenSSL并没有要求那么严格如果一个根证书没有可信选项那么它就默认该证书是一个可以用于任何用途的可信证书。目前OpenSSL的版本仅在根CA上支持可信选项设置从而实现在最终的CA上统一控制证书的用途比如允许CA颁发的证书用于SSL客户端验证或者SSL服务器验证等。当然OpenSSL的开发组承诺在以后的版本中将支持在所有证书中设置可信选项而不仅仅限于根证书。下面回到x509指令的显示世界中来让我们看看这些选项的具体含义和用法。trustout选项是最容易明白的一个选项了它会在输出的证书中加上可信的标记从而使其成为一个可信证书。x509指令可以接受的输入包括可信证书和普通的X.509证书但是如果没有trustout选项默认情况下输出的证书都会把可信选项去掉成为普通的X.509证书。当然如果你通过其他选项设置或者修改了证书的可信选项字段那么会自动输出一个可信证书。设置证书的信任选项在OpenSSL的指令中显得很简单使用addtrust选项就可以设置可信证书的用途你可以在这里使用任何有效的参数但是目前真正使用的参数仅仅包括clientAuthserverAuth和emailProtection。其中clientAuth参数表示用于SSL客户端验证serverAuth参数表示用于SSL服务器验证而emailProtection参数则用于S/MIME邮件的保护。相反clrtrust则将清除证书中所有可信选项的用途设置。相反如果你想禁止证书用于某种用途那么可以使用addreject选项该选项的参数内容和addtrust相同。而使用clrreject则可以清除所有设置好的禁止用途选项。我们猜你不会喜欢用一个证书的序列号来记忆或者标识一个证书虽然实际的计算机系统是如此的但毕竟人跟计算机还存在一些区别。那么我们的证书设计者充分利用了以人为本的设计理念提供了一种定义证书的名称的方法即证书的别名setalias选项就是为了让你拥有这种自由。证书别名通常是一个好记的字符串比如“OpenSSL‘sCertificate”等等看着比“0x00cd0e”愉快多了是不是?alias则事实上只是一个输出选项使用该选项输出的内容中就会包括证书的别名了。 证书签发转换选项signkeyclrextreqx509toreqdaysset_serialCAserialCAcreateserialextfile和extensions 首先来看看signkey选项这个选项指定了输入的保存私钥的文件路径。这个选项使用后会将输入的证书文件或者证书请求文件转换成一个自签名的证书。如果输入的是证书文件那么x509指令会执行下面的操作: 1 使用证书所有者名称替代证书签发者名称;2 更改证书有效期其中生效期从当前时间开始结束日期取决于days选项而其他扩展项和内容都会保留如果你想清除这些过时的扩展项那么就需要使用clrext选项;3 使用signkey提供的私钥重新签发证书。但是如果在使用signkey的时候同时使用了x509toreq选项过程则与上面不一样signkey提供的私钥将会被用来对生成的证书请求进行签名。如果输入的是证书请求文件事情就很简单签发一个自签名证书即可签发者名称当然跟证书持有人名称一致。通过上面signkey的介绍clrext选项的功能大家已经有所了解事实上clrext选项仅当x509指令通过一个证书创建另一个证书的时候有意义。也就是说仅当输入是证书并且使用signkey或者CA选项创建一个新的证书的时候clrext选项会将原来证书中的扩展项全部清除否则默认情况下所有扩展项都会被保留下来形成新证书的一部分。一般情况下x509指令会认为输入选项in输入的是一个证书如果你想输入的是一个证书请求那么使用req选项就是通知x509指令的唯一途径。有些情况下一些特殊需要总是会出现的比如将一个证书转换成证书请求这时候x509toreq选项就能帮助你达到这个目的。这功能看起来或许有些奇怪但是在证书到期续签的时候可能就有些用处了。使用这个选项的时候需要使用signkey选项提供相应的私钥在生产证书请求的时候进行数字签名。签发证书的时候需要指定有效期days选项就定义了有效期的长短默认情况下x509指令证书签发的有效期是30天。我们知道证书都有一个序列号这个序列号就像你的身份证号码一样独特而重要ca指令是通过文本数据库中的serial文件来保存确定的。而在x509指令中则可以有多种方法确定一个将要生成的证书的序列号。首先最直接的是可以使用set_serial选项来直接指定序列号该方法优先级是最高的如果使用了该方法后面的两种方法即便在指令中使用了也会被忽略。其次是可以使用CAserial选项指定序列号文件来提供序列号事实上所谓序列号文件事实上是一个仅包含一个十六进制正整数的文件。使用CAserial选项后指令会自动将该序列号文件中的整数加1并保存回文件默认情况下x509指令的序列号文件名称为证书文件名称加上.srl后缀比如输出的证书文件名为certpem那么指令会试图从文件cert.srl中获取序列号。最后如果你这个文件也没有(其实你真的可以自己用文本编辑器编一个)就使用CAcreateserial选项生成一个证书序列号文件该序列号文件保存的是2而所签发的证书序列号是1这时候你可以打开这个序列号文件好好研究一下了。有时候在证书中需要加入扩展项这时候可以使用extfile选项extfile选项指定的是一个扩展项配置文件。指定扩展项定义文件之后可能还需要使用extensions指定使用的扩展字段因为一个扩展项配置文件中可能存在多个扩展字段如果不使用该选项那么需要加入的扩展项应该定义在文件的默认字段(未命名字段)或者默认字段中应该包含一个名为extensions的变量来指明扩展项所在的字段。 证书显示名称格式选项nameopt 利用nameopt的参数完全可以显示所有人和签发者的中文信息包括名称、单位和城市等等。首先我们需要一个能够输入中文的控制台终端比如普通的中文Windows指令行界面。在该控制台可以按照正常的req指令生成一个证书其用户信息用中文填写完成从而得到一个中文的证书。如果你直接使用下面的指令验证证书是否过期 选项checkend这个选项非常简单实用目的就是验证输入的证书是否在有效期内。如果本选项返回0说明输入的证书没有过期如果返回是1则说明证书过期了 信息摘要算法选择选项md5md2sha1和mdc2 对于这些名词大家应该已经非常熟悉了它们是进行信息摘要时可能用到的四种算法在前面章节有对于这几种算法的详细介绍。信息摘要算法在证书中主要是用于CA颁发证书签名的时候具体到x509指令来说如果信息摘要算法变化了对于前面介绍的-fingerprint-signkey和-CA等证书信息的输入输出选项的结果都会有影响。在x509指令里如果没有特别指定默认使用的是MD5算法。由于DSA算法固定使用SHA1算法作为数字签名的信息摘要算法所以如果你使用DSA密钥进行数字签名则SHA1的使用将是固定不变的这些选项也就没有任何使用的必要。 engine选项 engine选项告诉x509指令尽可能使用Engine设备提供的加密函数和算法替代OpenSSL本身的函数。对于x509指令来说可能替代的算法包括:签名时使用的信息摘要算法、签名时使用的私钥加密算法、验证证书请求中的数字签名时使用的公钥解密算法、随机数函数及私钥数据等。  例子 查看一个证书的内容 CRL 当证书被CA吊销时它将被添加到该CA的证书吊销名单中CA中心必须定期发布更新吊销列表(CRL)以保证所有CA相关的应用都能及时得知证书的有效性信息。所谓CRL事实上就是一系列已经被吊销的证书序列号组成的文件并且为了确保该文件的真实性该文件经过了CA的合法签名。一般来说CRL都具备有效期限制其有效期由CA决定可能是一天、一周或者一个月等当然有效期越长其跟实际情况相差的可能性越大。CRL的颁发和公布都是由CA定期进行的发布的方式是多种多样的可以是在网上发布或者通过E-mail发布无关紧要。CRL的使用者是所有使用该CA签发证书的系统和用户他们需要随时获取最新的CRL并在进行证书验证的时候查看该CRL确定接收到的证书不在该CRL列表内(如果在该列表内则证书就是无效的了)。 crl指令功能概述和格式 OpenSSL提供了crl指令用于显示、处理和验证CRL文件信息而发布CRL文件则在前面介绍的CA指令中可以实现。下面是crl指令的格式和选项:  输入和输出格式选项inform和outform inform和outform选项指定了输入和输出文件格式相对应于in和out选项可以接受的格式包括PEM和DER编码格式默认接受的格式是PEM。 输入和输出选项in和out in选项指定了输入的CRL文件的路径文件的编码格式由inform参数决定。默认情况下输入的是标准输入设备。out选项指定了接受输出的文件的路径默认情况下输出目标是标准输出设备。其输出格式由outform参数决定。 输出显示内容选项hashissuernoouttextlastupdatenextupdate和date  hash选项显示CRL文件中CA签名的HASH值。isuer选项显示CRL文件签发者信息一般来说就是CA的信息。noout选项要求指令不输出编码CRL的内容。text选项要求指令输出CRL文件的可理解的形式也就是说能够让你一看就懂的形式。lastupdate和nextupdate选项分别显示CRL文件的最近更新时间和下次更新时间而使用date选项则同时显示上述两种时间。事实上所谓下次更新时间也就是本CRL文件失效的时间。 输出字符编码选项nameopt nameopt选项指定了如何显示主体名称和签发者名称主要用于显示名称中不同编码的内容。没有使用该选项时默认使用的是“oneline”参数。该选项可以同时使用多个参数每个参数间使用“”分开即可。具体的参数可以参照表10.4。 CA文件和目录选项CAfile和CApath CAfile指定一个CA证书文件该CA证书用于核实CRL中的签名是否正确和有效。CApath则告诉指令从一个目录中查找有效的CA证书此目录必须是标准证书目录所谓标准目录即OpenSSL要求的基于文件HASH值为文件名排序的一个目录详见x509指令的介绍。 简单的例子 把CRL文件的格式从PEM转化成DER:PKCS#12证书 事实上除了Microsoft的产品Netscape的浏览器也需要PKCS#12格式证书的支持。基于此OpenSSL除了在一般的指令中对PKCS#12证书提供支持还开发了专门用于处理PKCS#12证书的指令pkcs12用于PCKS#12证书的生成、解释和验证等。 pkcs12指令功能概述和格式 pkcs12指令功能总体来说可以分成创建PKCS#12证书和解释PKCS#12证书。创建PKCS#12证书即将普通的X.509证书和私钥封装成PKCS#12证书;解释证书可以将PKCS#12证书转换成X.509证书并提取出相应的私钥并可以输出其他必要的信息。一般来说PKCS#12证书的私钥是经过加密的密钥由用户提供的口令产生。所以在使用pkcs12指令编码或者解码PKCS#12证书的时候一般都会要求用户输入密钥口令。下面是pkcs12指令的格式和选项:需要把PKCS#12证书转化成X.509证书时仅仅用-in和-out选项就可以完成了。如果你想把X.509证书和其私钥封装成PKCS#12证书再增加-export一个选项即可轻松完成。当然如果你需要更加具体复杂的要求你需要了解的指令选项也会多一些。  输入和输出文件选项in和out 默认情况下输入和输出指定的都是标准输入输出设备。在解释PKCS#12证书的时候即没有使用-export选项的时候in选项的参数默认情况下是一个PKCS#12格式的文件它将被解释为单独的证书和私钥并总是以PEM格式写入到out选项指定的输出文件中。在创建PKCS#12证书的时候out选项参数输出的是一个PKCS#12格式的证书文件。in选项输入的文件是包含一系列证书和私钥的文件。这些证书和私钥必须是PEM编码的它们在该文件中的顺序不受限制但要求至少有一个私钥和其相对应的证书存在。如果存在其他附加的证书则这些证书都会被封装到输出的PKCS#12证书文件中。 输入和输出口令选项passinpassoutpassword pasin选项指定了使用输入文件的时候需要的口令源。如果是解释PKCS#12证书则是该证书文件解密口令源;如果是创建PKCS#12证书则是读取私钥文件时候可能需要的口令源。pasout选项则指定了输出文件时进行加密的口令源。如果是解释PKCS#12证书则是输出私钥加密口令源;如果是创建PKCS#12证书则是加密PKCS#12证书文件时可能需要的口令源。password选项提供的总是PKCS#12证书的加密口令源即在解释PKCS#12证书时其参数为读取PKCS#12证书需要的口令源;在创建PKCS#12证书的时候其参数为加密PKCS#12证书需要的口令源。口令源的形式多种多样可以是直接输入也可以是从文件、环境变量、标准输入输出等获取 输出内容选项nooutclcertscacertsnocertsnokeys和info 这些选项都是在解释PKCS#12证书时使用的noout选项告诉指令不要输出任何私钥和证书信息到输出文件中。clcerts选项告诉指令只输出客户证书(不是CA证书)到输出文件中。cacerts选项告诉指令只输出CA证书到输出文件中。nocerts选项告诉指令不要输出任何证书到输出文件中。nokeys选项告诉指令不要输出私钥到输出文件中。info选项告诉指令输出一些其他PKCS#12证书文件相关的信息如构成、算法及其迭代次数等。 加密算法选项desdes3ideaaes128aes192aes256和nodes 这些选项仅在解释PKCS#12证书的时候使用。desdes3ideaaes128aes192和aes256选项用于指定在输出私钥时对私钥进行加密使用的算法。默认情况下pkcs12指令会使用des3作为加密算法。nodes选项则告诉指令对私钥不进行加密处理。 nomacver和twopass 这两个选项使用较少也仅在解释PKCS#12证书的时候使用。nomacver选项告诉指令在读取PKCS#12证书之前不需要对文件进行MAC的完整性验证。twopass选项告诉指令提示输入完整性验证和加密需要的密码源。大多数PKCS#12软件实现都假设这两个密码是一样的不需要使用这个选项。 创建PKCS#12证书选项export 该选项在创建PKCS#12证书的时候必须使用告诉指令这时候需要创建一个PKCS#12证书而不再是解释一个已有的PKCS#12证书。 证书内容输入选项inkey和certfile 这两个选项在创建PKCS#12证书的时候使用。inkey选项指定一个包含了私钥的文件指令将从这个文件中读取创建PKCS#12证书需要的私钥。如果该选项没有使用则在in参数指定的输入文件中必须包含一个私钥。certfile选项指定向创建的pkcs#12证书中封装额外的证书这些证书存储在该选项的参数文件中可以是一个或者多个。 证书别名选项name和caname 这两个选项在创建PKCS#12证书的时候使用。name选项指定了证书和私钥的一个好记的别名该名称通常显示在需要导入该PKCS#12证书文件的软件中的证书列表中。caname选项用于为其他证书指定一个好记的别名该选项可以使用多次以为多个证书指定名称名称的顺序跟证书出现的顺序保持一致即可。该选项一般仅在IE里面有效在Netscape软件中则通常被忽视。 证书加密算法选项descertkeypbe和certpbe 这三个选项在创建PKCS#12证书的时候使用。descert选项告诉指令使用3DES算法加密证书在默认情况下指令使用3DES算法加密私钥但是使用40位的RC2算法加密证书。keypbe和certpbe选项分别指定对密钥和证书进行加密的算法。虽然所有的PKCS#5v1。5或者PKCS#12算法都是支持的但是OpenSSL还是建议你只用PKCS#12标准中的加密算法。这些算法包括DES3DESRC2和RC4等。这些参数的形式诸如:支持的具体算法和其参数形式见表11.1。 密钥用途选项keyex和keysig 这两个选项在创建PKCS#12证书的时候使用而且仅在Microsoft的IE和其他Microsoft软件中才有效。keyex选项指定密钥和证书用于密钥交换keysig则指定密钥和证书用于数字签名。如果仅使用keysig选项则密钥仅能用于进行签字。仅用于签名的密钥可以用来进行S/MIME签名、验证码(ActiveX控制签名)和SSL客户端验证。需要注意的是由于OpenSSL本身存在的BUG只有IE5.0和其后的版本才能够支持仅用于签名用途的密钥进行SSL客户端验证。 迭代次数选项nomaciternoiter和maciter 这几个选项在创建PKCS#12证书的时候使用而且仅在你需要兼容Microsoft的IE4.0的时候需要。因为算法通常使用普通口令产生密钥为了降低受到字典攻击的可能性可以将口令进行多次迭代从而产生复杂的口令。这通常以重复密码算法中的一部分步骤和降低速度为代价。MAC虽然一般用于验证文件的完整性但因为私钥和证书也是使用与其相同的口令所以MAC同样存在被攻击的可能性。通常情况下MAC和算法的迭代次数都设置为2048次如果使用了nomaciter和noiter选项迭代次数将分别降为1。显然这两个选项大大降低了文件的安全性所以除非不得已建议不要使用这两个选项。除了IE4.0不支持MAC迭代外大部分软件都支持多次MAC和算法迭代。maciter目前来说意义不大指明需要使用MAC迭代目前版本这已经是默认的只是为了兼容以前的版本该选项才没有取消。 其他选项chain和rand 这两个选项同样在创建PKCS#12证书的时候使用。chain选项告诉指令要建立一个完整的用户证书相关的证书链保存在PKCS#12文件中。指令会从一个标准的CA证书容器中寻找建立证书链需要的证书如果失败则视为发生致命性错误。这个功能当然比较特殊不过很多时候验证方确实需要被验证方提供完整的证书链来进行验证操作尤其当多级CA存在的情况下这种要求就是常见的了。随机数文件选项rand提供了产生随机数的参考种子文件。如果没有提供该选项那么程序会从标准输出设备的状态读取信息作为随机数种子。随机数文件可以为任意类型的文件。rand选项可以支持多个文件用分隔符隔开即可Windows平台使用“;”分隔OpenVMS系统使用“”分隔其他系统都使用“;”分隔。 例子 PKCS#7证书 PKCS#7格式的证书可以封装X.509标准证书、相关证书链上的CA证书和CRL这样就可以直接把PKCS#7证书发给验证方验证免去了把以上的验证内容一个一个发给接收方的烦琐了。微软对PKCS#7证书的支持依赖文件后缀名p7当然OpenSSL则是从来不关心后缀名的。OpenSSL对PKCS#7协议提供了将普通用户证书、CA证书和CRL封装成PKCS#7格式证书的指令crl2pkcs7此外还提供了pkcs7指令来解释PKCS#7格式证书下面就具体介绍一下crl2pkcs7和pkcs7指令。 crl2pkcs7指令功能概述和指令格式 crl2pkcs7指令名不符实并不仅仅是把CRL转换成PKCS#7证书。其实在OpenSSL中该指令是唯一可以生产PKCS#7证书的指令主要用于把CRL和一个或多个证书封装成一个PKCS#7格式的证书。并且CRL是一个可供选择项即PKCS#7证书里面不一定需要一个CRL。crl2pkcs7指令的格式如下:输入和输出格式选项inform和outform inform选项指出了输入的CRL文件的编码格式。目前只支持两种格式:PEM和DER。outform选项指出了输出的PKCS#7文件的编码格式。目前支持PEM和DER两种格式。 输入和输出选项inout和certfile in选项指定了存储输入CRL的文件名。此选项如果不指定默认采用标准输入。out选项指定了存储输出PKCS#7证书的文件名默认采用标准输出。certfile选项指定的文件可以包含一个或多个证书文件中的证书将会全部被封装到PKCS#7证书中这个选项也可以多次使用以加入多个证书。需要注意的是所有的证书都应该是PEM格式编码的。 不包含CRL的PKCS#7证书选项nocrl nocrl选项指定在输出文件中不包含CRL文件。一般情况下在输出的PKCS#7文件中包含CRL。指定此选项后操作过程中将不会去读输入文件中的CRL。 简单的例子 crl2pkcs7指令最常用的用法是用来生成PKCS#7证书。下面就是生成PKCS#7简单例子。pkcs7指令功能概述和指令格式 查看这个包含多个X.509证书和CRL信息的文件里面的内容OpenSSL提供pkcs7指令满足你的这种愿望。pkcs7指令的格式如下: (1)输入和输出格式选项inform和outform inform和outform选项指定了in和out选项相关文件的格式可以是PEM或者DER格式。 (2)输入和输出选项in和out in选项指定了输入的证书文件的路径文件的编码格式由inform参数决定。默认情况下输入的是标准输入设备。out选项指定了接受输出的文件的路径文件的编码格式由outform参数决定。默认情况下输出目标是标准输出设备。 (3)输出显示内容选项ptint_certstext和noout print_certs选项要求输出该PKCS#7证书文件内的所有证书和CRL该选项逐行输出所有证书的主题名和签名者。text选项要求输出证书的所有内容。noout选项要求不要输出编码结构的PKCS#7证书。 (4)engine选项 engine选项指定后所指定的Engine(通过唯一的id指定)会使用Engine设备指定的库或者硬件设备相关接口来处理本指令的一些操作。 (5)简单的例子 验证证书 证书的结构中的关键内容包括:序列号、公钥、用户名称、签发者、CA 签名和其他 一些附属信息等。证书验证过程就是依赖于这些信息和公钥对应的私钥进行。 通常的证书 验证过程包括以下要点: 1确认证书内容是正确的和完整的没有被篡改CA签名是正确的;2确认证书是有效的在有效期内并且没有被吊销(CRL中没有该证书序列号);3确认CA证书是可以被信任的证书如果CA证书不是根证书还要继续对CA证书进行验证;4通过与用户的交互基于证书中的公钥和公开密钥算法确认用户的身份。其中确认用户身份的过程是基于公开密钥算法的基本过程如下: 1被验证方发送自己的用户证书给验证方;2验证方提取证书中的公钥并产生一个随机数Rp使用该公钥加密该随机数得到加密的随机数Re并发给被验证方;3被验证方使用自己的私钥解密Re得到Rep并发回给验证方;4验证方对比Rp和Rep如果一致则验证通过否则验证不通过。从上述的过程可以知道因为证书中公钥对应的私钥仅真正的证书所有者才可能持有(理论上是这样的当然现实的系统和社会中不尽如此)所以如果被验证方能够正确解密使用该证书上的公钥加密的信息即可认为被验证方确实是证书的持有人也就可以确定其身份。无论何种类型的证书其验证过程都是基本一致的当然根据具体的情况其验证协议和要求提供的材料可能有一些区别。关于证书验证的更多情况也可以参考前面。不过在这一节我们关心的是验证证书的有效性而不对证书持有人的身份真实性进行验证。OpenSSL提供了证书验证的一些指令包括普通验证指令和一种标准的OCSP协议处理指令。 verify指令介绍 功能概述和指令格式 verify指令提供了证书或者说证书链的验证功能下面是verify指令的选项和格式:在验证过程中遇到什么错误虽然通常情况下这时候应该算作验证失败应该停止验证过程了但是我们OpenSSL中的verify指令还是不辞劳苦地将整个验证过程执行完。这样的好处是可以告诉用户在整个证书链的验证过程中存在的所有问题而不需要用户一个一个问题进行逐步排除。为了执行验证过程verify指令首先做的事情是试图从提供的所有证书里建立一个证书链证书链从提供的用户证书开始而结尾应该是一个根CA证书。证书链建立的规则是寻找当前证书的签发者证书如果一个证书的签发者就是其自己那么该证书就是根证书。如果verify指令不能成功建立一个证书链那么就认为验证失败。 寻找当前证书的签发者证书这个过程本身也是一个复杂的过程。在OpenSSL早期版本中(0.9.5a)第一个找到的持有者名称跟当前证书签发者名称一致的证书即被认为是当前证书的签发者证书。而在0.9.6和后面的版本中所有找到的持有者名称与当前证书签发者名称一致的证书都被认为是可能的签发者证书需要进行进一步的验证来确定。也就是说除了前面的条件当前证书的密钥标识字段内容必须跟候选签发者证书的密钥标识、签发者和序列号等相匹配此外候选签发者证书的密钥用途扩展字段也应该包含允许签发证书的功能。建立证书链的时候程序首先查找不信任列表如果找不到当前证书的签发者证书则开始在信任列表中查找证书。而根CA证书总是在信任列表中被找到的。如果需要验证的证书本身就是一个根证书那么必须在信任证书列表中找到一个完全一致的证书才能认为是验证通过。建立一个完整证书链后verify程序开始检查每一个非信任证书的扩展项是否跟purpose选项提供的参数内容相一致。当然如果purpose选项没有出现则在本步骤verify指令将不进行任何操作。需要验证的证书或者“叶子”证书其扩展项必须跟要求验证的purpose参数一致其他CA证书也必须是有效的证书。完成上述步骤后verify开始检查根CA证书的信任设置以确定其是否支持purpose的要求。OpenSSL为了兼容以前的版本假定如果CA证书没有任何信任设置则默认为支持任何用途。如果你使用的是0.9.7以后的版本很幸运OpenSSL将支持CRL验证的操作这时候verify将根据CRL检查整个证书链的每个证书是否有效即没有被管理员吊销。最后verify程序将检查整个证书链上所有证书的有效期根据当前的系统时间进行检测。需要注意的是各个证书的数字签名也是在这个最后的时刻进行检验的。通过上面所有的验证步骤证书验证才算成功否则任何一步的失败都意味着证书验证不通过。 CA证书选项CApath和CAfile CApath选项用来指定我们信任的CA的证书存放目录。但是这些证书的名称应该是下面这样的格式:xxxxxxxx.0(xxxxxxxx代表证书的哈希值可以参看x509指令的-hash选项)。CAfile选项用来指定我们信任的CA证书文件其中可以包含多个CA证书。目前只支持PEM格式的文件 非信任证书选项untrusted untrusted选项用来指定非信任证书文件同样该文件可以包含多个PEM格式的证书。所谓非信任的证书文件一般是指在构造证书链的时候需要使用的CA证书但一般都不是根证书。你千万不要以为这是不被信任的证书。通常CRL也可以通过这个选项指定的文件输入到verify验证过程中。 证书用途选项purpose 此选项主要验证证书的扩展字段显示证书的用途。如果没有设置此选项那么verify将不会对证书链进行验证操作。目前purpose支持的参数包括:sslclientsslservernssslserversmimesign和smimeencrypt。 验证选项isuer_checkscrl_checkcrl_check_al和ignore_critical issuer_checks选项告诉指令输出在查找签发者证书过程中的详细信息从而可以知道每个候选签发者证书被拒绝的原因。crl_check选项告诉指令检查被验证证书的CRL如果不幸CRL中存在被验证证书的序列号则证书将不能通过验证。CRL通过untrusted选项的参数输入crl_check_all选项告诉指令检查证书链中所有证书的CRL即不仅仅要对被验证证书是否被吊销进行验证还要对整个证书链中其他证书是否被吊销进行验证ignore_critical选项告诉指令可以忽略一些比较少用的扩展项即如果该扩展项指令没有处理的话则忽略。 如何输入被验证的证书? 在verify指令中在指令所有参数最后面输入要验证的证书文件名即可指定需要验证的证书。如果有多个证书文件需要验证可以以空格为间隔一起列在后面但是这些证书都应该是PEM格式的数字证书。如果不提供证书文件则指令将试图从标准输入中读取被验证的证书。使用verbose选项指令将把验证过程中的所有详细过程输出。engine选项用来指定可以用于替代OpenSSL的函数库的其他算法库或者硬件详见前面章节。 诊断证书验证结果 如果验证操作有问题OpenSSL提供了一些输出来让我们弄明白到底出现了什么问题虽然这些信息看起来有些难懂不过还是有用的。诊断信息输出格式如下: 第一行说明哪个证书文件出问题后面是其证书的主题。第二行说明错误号验证的深度并给出错误的解释虽然这些解释不甚明了。其中验证深度是从0开始计算的。表10-6给出了错误号及其描述的详细说明。需要注意的是有的错误虽然有定义但没用使用这里用unused标识。 例子 verify指定的选项应该是较少的用起来也非常简单。只需要按上述的各个选项的操作进行。下面是证书certpem验证的例子此证书用根证书cacert.pem生成: 在线证书状态服务协议指令 OCSP 在许多情况下需要验证证书真实性的人(当然也可能计算机或者程序)并不能完成证书验证的过程也就是说必须提供一种手段或者服务能够帮助完成证书验证的需要。这就是为什么OCSP协议(OnlineCertificateStatusProtocol)即在线证书状态协议会出现在我们面前的原因。OCSP协议使得普通证书应用程序可以通过服务方式知道一个特定证书的(吊销)状态从而使得普通程序不需要了解证书验证的细节和实现方式。OCSP接受一个客户端发来的证书验证请求信息(通常是以HTTP协议发出)然后OCSP查询证书库的状态。当然用户请求里面只是包含了证书的一些关键信息而并不需要一个完整的证书。根据结果OCSP响应器一般返回给客户端的状态信息包括三种:1良好说明请求证书是正确的而且没有被吊销;2吊销说明证书已经被吊销;3未知证书不在该OCSP响应器的范围内。为了防止可能发生的欺骗每一个OCSP返回的回应信息都有签名而签名者必须是用户所信任的也就是说用户还必须对每一个回应信息进行验证。在OpenSSL实现上这个签名者可能是以下三种之一。1 被验证证书的CA。即回应信息签名是用验证证书的CA证书签发的。2 被验证证书CA特殊授权的OCSP响应器。即使用OCSP本身的证书签发回应信息OCSP的证书跟被验证证书是同一个CA颁发的并且OCSP证书的用途被指明具有OCSP签名的权限。3 被信任的OCSP响应器。即使用OCSP本身的证书签发回应信息OCSP证书本身的CA的根CA在信任设置里面必须是明确指明是可以用于OCSP签名的或者是用户明确定义可以信任的OCSP响应器。可见OpenSSL的实现跟OCSP协议规定的是基本相符合的虽然在第三种方式上不完全一致。OpenSSL对OCSP回应信息的验证也是通过基于OCSP证书建立一个证书链来进行的关于OCSP更多的详细内容在RFC2560中有明确定义。 功能概述和指令格式 OpenSSL提供的指令总是超出人们的预期这次看到的ocsp指令也不例外。它几乎可以完成大部分OCSP协议通常的功能。该指令既可以用来输出OCSP请求和应答内容也可以创建OCSP请求并发送给一个OCSP服务器甚至它还可以作为一个OCSP服务器运行。下面是ocsp指令格式和其参数:ocsp指令里大部分选项都是用于测试和调试目的的一般情况下CAfileCapath和VAfile才是要经常使用的选项。 ocsp使用的时候可以作为客户端或者服务器两种模式下面我们对其参数的具体介绍也分为这两部分来进行。区分ocsp指令在服务器模式还是在客户端模式工作的标志就是是否使用index选项:如果使用index选项就是在服务器模式下工作否则就是在客户端模式下工作。 输入和输出选项outreqoutrespoutreqin和respin out选项指定通用的输出文件可以在服务器模式或者客户端模式使用默认情况下使用标准输出设备。一般来说只有可读写的信息会在out参数指定的文件中输出如提示信息、文本的请求或者响应解释信息等。reqout选项告诉ocsp指令输出OCSP请求信息并且存储在参数指定的文件中。respout则告诉指令输出OCSP响应并存储到该参数指定的文件中。上述选项输出的请求和响应都是以DER格式存储的。这两个选项同样都可以用于客户端和服务器模式。reqin和respin选项分别告诉指令从这两个选项指定的文件中读取OCSP请求或者OCSP响应。如果创建请求或者响应的选项出现如certserial或者host选项生效那么这两个选项将会被自动忽略。reqin选项在服务器模式和客户端模式都可能使用而respin选项则仅在客户端模式有效。 输出内容选项req_textresp_text和text req_text选项和resp_text选项分别告诉指令输出证书请求或者证书响应的文本信息如果使用text选项则指令将同时输出请求和响应文本信息。这些输出会保存在out指定的文件中或者标准输出设备中。这些选项在服务器和客户端模式都可以使用。 证书相关选项issuercert和serial isuer选项指定存储要验证证书的签发者证书的文件该证书必须是PEM格式的。该选项可以重复使用多次以选择多个签发者证书。该选项在创建OCSP请求的时候是必须的。cert选项指定要验证的证书即加到OCSP请求中的证书。签发该证书的CA证书必须在issuer选项中指定否则指令就不能正常执行。serial跟cert选项的功能一样用于向OCSP请求中增加证书不同的是该选项使用证书序列号来标识要加入的证书。该序列号默认是以十进制表示如果在参数前增加了0x则认为是十六进制。如果你要输入负数序列号(似乎是很奇怪的需求)只要在输入参数前面增加“-”号作为标识即可。 请求相关选项signersignkeynonce和no_nonce 如果需要对OCSP请求进行签名则可以利用signer选项来指定签名的证书其相应的私钥则可以在signkey选项指定的文件中输入。如果没有使用signkey选项则ocsp指令将从signer选项指定的文件中读取私钥。如果signer和signkey都没有使用那么OCSP请求就不会被加密。为了区分每个请求OCSP定义了所谓的nonce事实上它是一个使用摘要算法生成的跟时间相关的随机数为了防止重放攻击等行为的发生。使用reqin输入已有OCSP请求的时候默认情况下是不会向请求中增加nonce的如果选择了nonce选项则将强制向OCSP请求中增加nonce扩展项。相反当使用ocsp指令创建新的请求的时候(使用certserail或者host选项等)默认情况下会在请求中增加nonce扩展项如果不想使用nonce扩展项则可以使用no_nonce选项去除请求中可能增加的nonce扩展项。 OCSP响应器地址选项hostpath和url OpenSSL提供给我们的ocsp指令不仅仅可以处理一些OCSP请求或者响应信息还可以实时模拟一个OCSP客户端即时产生OCSP请求发送给指定的OCSP响应器并得到返回的响应信息。OCSP响应器一般提供基于HTTP或者HTTPS的服务其定位一般都是通过IP地址、端口和HTTP文件路径来进行。host选项参数指定了OCSP响应器的地址和服务端口一般是host:port的方式。而path选项则指定了HTTP文件的路径名默认情况下使用“/”。url选项是另外一种指定OCSP响应器地址的方式使用HTTP或者HTTPS请求的格式。事实上在OpenSSL的ocsp指令中url参数也是被解释成host和path参数进行实际连接的建立的。 响应验证证书选项CAfileCApathverify_certstrust_other和VAfile CAfile和CApath选项大家已经非常熟悉它们用来指定CA证书文件或者一个标准的存放CA证书文件的目录这里输入的CA文件用于验证响应信息的签名。很多OCSP响应器在返回的响应信息中不会加入完整的OCSP证书那么这使得客户端在验证响应信息的时候就会有一定麻烦。为了兼容这种情况verify_certs选项可以指定增加一个或者多个证书在验证OCSP响应时候可以查找使用这些附加的证书。trust_other选项告诉指令verify_certs指定的证书都是可信任的不需要对这些证书进行进一步的验证工作这时候指令不会执行完整的证书验证过程这对于不能够建立完整证书链的情况就非常有帮助。VAfile选项的功能是verify_certs和trust_other选项的综合该选项指定的证书都是默认为可信任的附加证书不需要进行进一步验证。 响应验证策略选项noverifyno_signature_verifyno_cert_verifyno_cert_checksno_internno_chainvalidity_period和status_age noverify选项告诉指令对OCSP响应签名和nonce字段不进行任何验证该选项事实上放弃了所有对OCSP响应的验证。no_signature_verify选项告诉指令不用验证OCSP响应中的签名信息即便签名无效。no_cert_verify选项告诉指令不用验证响应签名者的证书也就是说任何人签名的响应都是有效的。no_cert_checks选项则告诉指令对响应签名证书的状态不用做任何附加的检查即如果证书已经被吊销或者过期也是不会被发现的。上述的选项因为都在不同程度降低了响应验证的强度和响应的安全性控制所以理论上一般仅在测试的时候使用上述选项。no_intern选项告诉指令忽略OCSP响应中包含的证书信息在这种情况下必须使用verify_certs或者VAfile选项来增加额外的OCSP响应者证书以保证验证响应签名过程的顺利完成。no_chain告诉指令不要使用响应中的证书作为附加的非信任CA证书也就是说不要让响应中的证书增加到验证过程中建立的证书链中去这确保了验证过程中使用的证书完全是由用户来控制。每个证书响应都会包括一个有效期这个有效期由一个notBefore字段和一个可选的notAfter字段组成当前的时间必须在这两个字段规定的时间之间响应才有效。但是这个时间间隔有时候是非常短的可能只有几秒而实际系统的客户端和服务器的时间可能不同步存在误差。为了避免这种情况导致响应失效OpenSSL提供了validity_period和status_age选项来设定可以允许的时间误差值其参数单位是秒。其中validity_period选项适用于notAfter扩展项存在的情况下其设定的是一个误差秒数值默认值是5分钟。如果notAfter扩展项不存在这一般意味着该响应只是即时有效这时候可以使用status_age选项来设定有效期即notBefore时间比当前早的时间不应该超过status_age选项设定的值。默认情况下这项检查是不会执行的即响应在notBefore时间后总是有效。 OCSP服务器选项index和CA 上面介绍的选项大部分是用于处理OCSP请求、OCSP响应或者模拟客户端事实上ocsp还可以用于模拟一个OCSP响应器(服务器)。index选项是否在指令中出现是区分ocsp指令运行在服务器还是客户端的标记如果使用了index选项则表明指令已经运行在OCSP服务器(或者说响应器)的模式下。显然OCSP响应器就是为了处理OCSP请求的在OpenSSL的ocsp指令中OCSP请求的输入方式是灵活多样的:第一种是指令行方式即直接在ocsp指令行中输入使用issuer和serial参数产生请求信息;第二种是采用文件输入方式即使用reqin选项指定一个要处理的OCSP请求;第三种方式是采用其他OCSP客户端输入即定义好OCSP运行的服务端口port或者服务URL即可。index选项跟我们在ca指令中看到的index选项相同指定的是OpenSSL提供的模拟CA中的证书库文件该文件包含了该CA所有颁发的证书信息和其(吊销)状态。在服务器运行模式下CA选项是必须使用的它指定了index证书库相应的CA证书文件。 OCSP响应签发者选项rsignerrkey和resp_key_id OCSP响应必须是经过签名的所以在服务器模式下rsigner选项是务必要使用的它指定了用于对OCSP响应签名的证书。rkey则指定了rsigner证书选项相对应的私钥如果rkey选项在指令中没有出现那么在服务器模式下指令会从rsigner指定的文件中读取用于响应签名的私钥。OCSP响应被签名后还需要在响应中标识用于签名的私钥默认情况下使用的是证书主题名。如果使用resp_key_id选项则将使用私钥ID标识OCSP响应信息签名私钥。 OCSP响应内容选项rotherresp_no_certsnmin和ndays 如果想在返回给客户端的响应信息中包含其他附加证书信息(可能用于客户端验证响应签名时使用)那么可以使用rother选项指定存储这些附加证书的文件。相反如果不想在响应信息中放入任何证书(包括签发响应的证书)那么可以使用resp_no_certs选项。nmin和ndays选项用来填充响应信息中的nextUpdate字段该字段告诉客户端下一次吊销列表更新的时间将会在多长时间之后nmin和ndays分别以分钟和日为单位进行定义。如果在ocsp指令中这两个选项都没有使用那么nextUpdate字段就会从响应信息中删除这意味着吊销列表随时都会进行更新。 OCSP服务器运行方式选项port和nrequest 这两个参数仅在ocsp指令以服务器方式运行且请求是从OCSP客户端输入的情况下使用。其中port选项定义了OCSP服务器的服务端口而nrequest选项则告诉指令在接受和处理该参数指定数量的OCSP请求后退出运行状态。事实上还有其他一些参数没有一一介绍比如engine选项其意义跟其他指令中的同名选项是一样的即使用第三方密码设备或者密码库来执行一些运算操作。读者可以根据指令的使用和源代码的阅读来进一步了解这些指令的更多参数。
http://www.pierceye.com/news/288075/

相关文章:

  • 建设银行网站连不上成都网站快照优化公司
  • 网站 永久关停 请示广州网站建设骏域网站
  • 个人建站模板外国网站翻墙怎么做
  • 保定网站设计制作公司有经验的中山网站建设
  • 免费网站建设那个好wordpress本地怎么上传服务器
  • 自己做的网站加载慢WordPress模板首页文件是啥
  • 教学网站建设网站建设岗位有哪些
  • 网站建设合同的验收表网页网站的区别是什么
  • 开福区网站建设中wordpress调用所有栏目
  • 网站建设的流程是什么意思青岛做网站公司
  • 什么网站有项目做中铁建设企业门户网
  • 网站域名商代理商安卓商店
  • 深圳中英文网站建设广州知名设计公司排名
  • 一个公司设计网站怎么做的蜜桃传奇免费网页版
  • 网络推广网站培训班有人用wordpress默认主题
  • 网站建设 后台南宁做网站方案
  • 在线制作插画网站网站建设有哪些公司
  • 合肥的网站建设剂屏自己可以做开奖网站吗
  • 官网设计比较好看的网站学校网站建设对教学的意义
  • 济南建站推荐企汇优见效付款毕设代做网站招聘
  • 泰然建设网站免费软件app下载大全正能量网站
  • 张掖市网站建设北京代理记账财务公司
  • 中铁建设集团网站网络公司手机网站
  • 站长工具是什么意思建设银行网站 开户行怎么查
  • 做简历模板的网站都有哪些wordpress是啥东西
  • 网站流量渠道湖州做网站优化
  • 汽车网站哪个好预付的网站开发费用怎么入账
  • 网站代管理哪个网站有介绍拿到家做的手工活
  • 惊艳的网站网站建设实训过程报告
  • 秦皇岛做网站公司企业网站备案需要什么