从密码学开始,https证书的前世今生

网络通信安全中的SSL/TLS证书机制解决了什么需求?它是如何工作的?动手小实验?

主题:计算机网络中的安全

安全通信四要素

  • 机密性
    • 内容加密
    • 防被他人解惑得知通信内容
  • 报文完整
    • 完整性校验
    • 防被恶意篡改或被意外修改
  • 端点鉴别
    • 身份声明
    • 防中间人攻击
  • 运行安全
    • 防火墙
    • 防非法侵入、远程操作
    • 对外通信的窗口,变成别人的后门了,就尴尬了

机密性:加密与解密

  • 加密,即(明文, 算法, 密钥) ➔ 密文的映射,或是加密(明文,算法(密钥))➔密文
  • 解密,即(密文, 算法, 密钥) ➔ 明文的映射,或是解密(密文,算法(密钥))➔明文

密钥是算法的一部分

  • 对于一套固定的,加密/解密的机制,机制中的一部分可以被抽象出指导性的数据。这部分指导算法如何工作的数据,就是密钥。
  • 例如,考虑一个简单的加密算法。
    • 这个算法只能加密26位小写英文字母
    • 加密时对明文的数据逐字符加密
    • 明文➔密文如下:a➔bb➔c,…,z➔a
  • 对于这一算法,加密就是1个字符后移1位。密钥就是(1,1)。解密所用的密钥也是(1,1)

对称性加密与非对称加密

  • 对称性加密
    • 加密(明文,算法(密钥))➔密文
    • 解密(密文,算法(密钥))➔明文
  • 非对称性加密
    • 加密(明文,算法(密钥A))➔密文
    • 解密(密文,算法(密钥B))➔明文

对于上文中表述的算法,显然,必须用和加密时相同的密钥来解密,才能得到原始的明文。这就是对称性加密的算法。

上文的加密算法可以数学化的表达为,将 a~z 理解为 27 进制的 1~26(0用于填充置空),加密是给明文加上固定的值,解密是从明文减去固定的值。加密和解密互为一个简单可逆的关系。

想象这样一个加密算法,加密以后不能简单地从密文进行逆运算来得到明文,而是可以通过对密文做另一个确定性的运算来得到明文。那么这样的一个算法,加密和解密就不一定是彼此的数据逆运算,密钥也多半是不一致的(但可能的共轭的,既互为加密/解密对)。这样密钥不一致的算法,被称为非对称性加密算法。

会话密钥

下文中讲解了常用的非对称加密算法 —— RSA。可以看到 RSA 算法中大量的指数幂计算会大量占用计算资源。在实际使用中,通常并不直接用 RSA 来加密全部数据,而是结合 DF 算法等,协商出仅用于此次会话的对称加密临时密钥。对称加密可分为块加密流加密,常见的一般是块加密。块加密通过块填充解决复杂度更高的大密钥无法加密小数据块的缺陷,通过块链接(CBC)应对 HTTP 报文中常见形如 HTTP/1.1 的选择明文攻击。对称性加密的复杂度已足以保证单次会话的机密性。块加密通常通过函数模拟映射表,(可能是以加法为主要运算),对计算资源的占用较少。

DES 用软件实现要比 RSA 快 100 倍,用硬件实现则要快 1000 - 10000 倍 [RSA Fast 2012] —— 《计算机网络·自顶向下方法》

RSA算法

RSA 是一种非对称性加密算法。

RSA 制作密钥对

理论背景

  • 对于如下表达式
    • 算法约定模数 $n = pq$
    • 公私钥标准数 $z = (p-1)(q-1)$
    • 要求 $p, q\ 均为质数$
  • 指定一个与 $z$ 互质的数 $e$,并找到满足如下式子的 $d$
    • $ed\ mod\ z=1$
  • 则有公钥是(n,e),私钥是(n,d)

举个例子

  • 对于指定的算法约定数:33
  • 找一对儿质因数:3, 11
  • 标准数 $z$ 是多少:20
  • 选一个满足要求的公钥 $e$:
    • $质数\ e\in(1,z)$,只要和 $z$ 互质就 OK,通常直接选质数
    • 例如 e=3,则公钥是(33,3)
  • 算出私钥:$3d\ mod\ 20 = 1$,$d$ 可以是 7,27,47 … 当然,我们选择,7。因为 $d$ 也最好是 在 (1,z) 上和 $z$ 互质的数。

RSA 加解密 过程模拟

公钥和私钥都能加密,就是解密只能用对方来解

显然,这只是一个简化的模拟实验。真实的 RSA 算法,p、q 的数量级都在 1024 比特以上

加密:(n, key) 是 (33, 3)

源数据 数字化 x 计算 mod (x^key, n) 密文数字值
n 1 mod(1^3, 33) = 1 1
i 2 mod(2^3, 33) = 8 8
c 3 mod(3^3, 33) = 27 27
e 4 mod(4^3, 33) = 31 31

解密:(n, key) 是 (33, 7)

密文字面值 数字化 x 计算 mod (x^key, n) 明文数字值
不重要,不管 1 mod(1^7, 33) = 1 1
不重要,不管 8 mod(8^7, 33) = 2 2
不重要,不管 27 mod(27^7, 33) = 3 3
不重要,不管 31 mod(31^7, 33) = 4 4

数学计算的 golang 代码

package main

import (
"fmt"
"math"
)

var Msg = []float64{1, 2, 3, 4}

func main() {
rsaEncode := generateRSA(33, 3)
rsaDecode := generateRSA(33, 7)
for _, v := range Msg {
fmt.Printf("%.0f -> %.0f -> %.0f\n", v, rsaEncode(v), rsaDecode(rsaEncode(v)))
}
// i := float64(0)
// for i < 100 {
// fmt.Printf("%.0f -> %.0f -> %.0f\n", i, rsaEncode(i), rsaDecode(rsaEncode(i)))
// if i != rsaDecode(rsaEncode(i)) {
// fmt.Println("Aborted!")
// break
// }
// i++
// }
}

func generateRSA(n, key float64) func(x float64) float64 {
return func(x float64) float64 {
return math.Mod(math.Pow(x, key), n)
}
}

运行结果

image-20231030162337855

稍微改一下代码,可以看到,程序可以正常处理 0~32 的明文值,而在 33 以上的明文值,会映射回 0~32 内。

跑完了才想起来,mod(x, 33),有效输出可不就是 0~32 么。🤣憨包,这还要跑代码验证hhh

RSA 加解密 数学分析

  • 起始状态:
    • M 明文
    • E 密文
    • p,q 分析用数,质数
    • n 分析用数,大数,模数 $n=pq$
    • z 分析用数,$z=\left(p-1\right)\left(q-1\right)$,$ed\ mod\ z=1$
    • e 加密密钥,幂级数
    • d 解密密钥,幂级数
  • 欧拉函数、同余定理的简化推论
    • 条件
      • $p,q\ 均为素数$
      • $n=pq$
      • $z=(p-1)(q-1)$
    • 结论
      • $x^y\ mod\ n = x^{y\ mod\ z}\ mod\ n$
  • 加密:
    • $E=M^e\ mod\ n$
  • 解密
    • $E^e\ mod\ n=(M^e\ mod\ n)^d\ mod\ n=M^{ed}\ mod\ n\Rightarrow{M} $
    • 即欲证 $M^{ed}\ mod\ n\Rightarrow{M}$
  • 即证 $M^{ed}\ mod\ n = M^{ed\ mod\ z}\ mod\ n\Rightarrow{M}$
  • 因为在构造 $e,d$ 时,我们特意选择了能满足式子 $ed\ mod\ z=1$的 $e,d$
  • 即证 $M^{ed}\ mod\ n = M^{ed\ mod\ z}\ mod\ n=M\ mod\ n\Rightarrow{M}$
  • 显然,只要 $M \in [0,n)$,就有 $M\ mod\ n\Rightarrow{M}$

RSA 密钥文件 探索

asn1, PKCS#1, PKCS#8

asn1 schema playground: https://asn1.io/asn1playground/default.aspx
PKCS#8 RFC5208: https://datatracker.ietf.org/doc/html/rfc5208
asn1 decoder: https://lapo.it/asn1js/

asn1 是一种结构化的编码语言,可以定义出各种文件的 schema。在各种RFC约定的文件格式里,DER、BER,又例如 PKCS#1、PKCS#7、PKCS#8、PKCS#12 等,这些都是固定 schema 的 asn1 数据。网站 asn1 decoder 可以解析 rsa 私钥文件,比较友好地展示其中的格式和内容。也可以通过网站自己提供的 example 来感受 PKCS 文件都有哪些域。下面,我们做一个简单的实验。

LAB 私钥/公钥 文件内容理解

# 博主当前 openssl 的版本
$ openssl version
OpenSSL 3.1.2 1 Aug 2023 (Library: OpenSSL 3.1.2 1 Aug 2023)
# 生成一个未加密的 rsa 512 位私钥
$ openssl genrsa -out rsa.key 512
$ cat rsa.key
-----BEGIN PRIVATE KEY-----
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEArygy6oPqQXzPPC/c
qTSdBSuo3QFJuExrihifYVNypUrJJgOZGPtjt+o5a6faU64F2BtqlFq7m7WlaOzv
hs54aQIDAQABAkBJjcb75lN8Fq5r5ulyAM8jebcav8y2YRkTz802MLXHJROuLP6J
2bmkab1rF6KX02u0yUCiQsfxRDOSwMxAWPdVAiEA2nEwRB/09g0i9MwCFzglE+ll
yli1rmvJlrGnTl4buWcCIQDNRczN+XW42pGF0qP4Q534zgEK4oJczW5qwm5Q/juN
rwIhALxk5mW60f/rcHyD/kGcUI4Nu5Z6T6bwm1n2Of8itvJ9AiA2XKHcepAeoGOh
mSMrgFy5o3TLOSllAlKXm14zvOBwqQIhAJJrqE0EPT1izKR0cNMwyTAo7NXAwPxF
BcUQeGsmQK2Z
-----END PRIVATE KEY-----
# [MacOS] 将 rsa.key 载入剪贴板,用来粘贴到asn1在线解析网
$ pbcopy < rsa.key

image-20231031154344363

我没细看文档,直接问的 sage,数据结构大概如下

PrivateKeyInfo
├── version (int 0)
├── privateKeyAlogrithm (seq)
│ ├── algorithm (object-identifier rsaEncryption)
│ └── parameters (any NULL)
└── privateKey
├── seq-int-0 (版本号 0)
├── seq-int-1 (e 公钥 512 位)
├── seq-int-2 (n rsa约定模数 65537)
├── seq-int-3 (d 私钥 511 位, 实际会填充前导 00)
├── seq-int-4 (p 第1个质数因子)
├── seq-int-5 (q 第2个质数因子)
├── seq-int-6 [第1个质数指数]
├── seq-int-7 [第2个质数指数]
└── seq-int-8 [RSA密钥系数]

Q: 可以从私钥直接导出公钥么

A: 可以,因为 key 文件包含了完整的 RSA 参数

# 生成私钥,这次整个 AES256 加密了的。可以去 asn1 decoder 上看看,其实也是 PKCS#8
openssl genrsa -out rsa.key -aes256 -passout pass:12345 512
# 从私钥中导出公钥,记得输入密码 12345
openssl rsa -in rsa.key -out rsa.pub -pubout

image-20231031213335001

公钥文件就很简单了,只有 (e[512],65537)

Q: 用实验里的命令尝试查看自己的 ~/.ssh/id_rsa,为什么失败了

A:详见 man ssh-keygen

ssh-keygen 默认生成的是 OpenSSH-specific 的格式,而不是 openssl 生成的 PKCS#8 或者 PKCS#1。PKCS#1 仅支持 rsa,PKCS#8 则兼容其他算法。PKCS#1 基本是见不到了。就算遇到了,openssl pkcs8 也可以把它转成 PKCS#8。ssh-keygen 可以把 OpenSSH-specific 转换为 openssl 可以接受的格式,但是只保留公钥,私钥是转不出来的。

# 这俩,效果是一样的
ssh-keygen -e -f ~/.ssh/id_rsa.pub -m pem | openssl rsa -pubin
ssh-keygen -e -f ~/.ssh/id_rsa -m pem | openssl rsa -pubin

# man ssh-keygen 部分摘要
-e This option will read a private or public OpenSSH key file and
print to stdout a public key in one of the formats specified by the -m option.
The default export format is “RFC4716”.
This option allows exporting OpenSSH keys for use by other programs,
including several commercial SSH implementations.

DF算法 TLS1.2/1.3 握手流程 证书文件理解 流加密 各个级别的证书文件区别的介绍

<未完待续…>

CSR 证书签发请求

PKCS #10: Certification Request Syntax Specification

https://datatracker.ietf.org/doc/html/rfc2986

X.509 证书

RFC 真是优雅极了的设计文档,爱了爱了

X.509 Public Key Infrastructure Certificate RFC5280

https://datatracker.ietf.org/doc/html/rfc5280#section-3.2

注意:RFC5280 声明的 X.509 Certificate 也有被之后的 RFC 文档做部分的更新、扩展、修正。重在理解。

证书的分类

This specification covers two classes of certificates: CA certificates and end entity certificates.

CA certificates may be further divided into three classes: cross-certificates, self-issued certificates, and self-signed certificates.

Cross-certificates are CA certificates in which the issuer and subject are different entities.

Cross-certificates describe a trust relationship between the two CAs.

Self-issued certificates are CA certificates in which the issuer and subject are the same entity.

Self-issued certificates are generated to support changes in policy or operations.

Self-signed certificates are self-issued certificates where the digital signature may be verified by the public key bound into the certificate.

Self-signed certificates are used to convey a public key for use to begin certification paths.

End entity certificates are issued to subjects that are not authorized to issue certificates.

TBS Certificate 简介

The sequence TBSCertificate contains information associated with the subject of the certificate and the CA that issued it.

Every TBSCertificate contains the names of the subject and issuer, a public key associated with the subject, a validity period, a version number, and a serial number;

some MAY contain optional unique identifier fields.

The remainder of this section describes the syntax and semantics of these fields.

A TBSCertificate usually includes extensions.

Extensions for the Internet PKI are described in Section 4.2.

CertificateModule DEFINITIONS ::= BEGIN

Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING
}

TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1,
issuer Name,
subject Name,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
validity Validity,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
extensions [3] EXPLICIT Extensions OPTIONAL
-- If present, version MUST be v3
}

Version ::= INTEGER {
v1 (0),
v2 (1),
v3 (2)
}

CertificateSerialNumber ::= INTEGER

Validity ::= SEQUENCE {
notBefore Time,
notAfter Time
}

Time ::= CHOICE {
utcTime UTCTime,
generalTime GeneralizedTime
}

UniqueIdentifier ::= BIT STRING

SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING
}

Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension

Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING
-- contains the DER encoding of an ASN.1 value
-- corresponding to the extension type identified
-- by extnID
}

AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}

Name ::= CHOICE { -- only one possibility for now --
rdnSequence RDNSequence
}

RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue

AttributeTypeAndValue ::= SEQUENCE {
type AttributeType,
value AttributeValue
}

AttributeType ::= OBJECT IDENTIFIER

AttributeValue ::= ANY -- DEFINED BY AttributeType

DirectoryString ::= CHOICE {
teletexString TeletexString (SIZE (1..MAX)),
printableString PrintableString (SIZE (1..MAX)),
universalString UniversalString (SIZE (1..MAX)),
utf8String UTF8String (SIZE (1..MAX)),
bmpString BMPString (SIZE (1..MAX))
}

-- ISO arc for standard certificate and CRL extensions
id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt (2) ds (5) 29}

-- authority key identifier OID and syntax
id-ce-subjectAltName OBJECT IDENTIFIER ::= {id-ce 17}

SubjectAltName ::= GeneralNames

GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName

GeneralName ::= CHOICE {
otherName [0] OtherName,
rfc822Name [1] IA5String,
dNSName [2] IA5String,
x400Address [3] ORAddress,
directoryName [4] Name,
ediPartyName [5] EDIPartyName,
uniformResourceIdentifier [6] IA5String,
iPAddress [7] OCTET STRING,
registeredID [8] OBJECT IDENTIFIER
}

OtherName ::= SEQUENCE {
type-id OBJECT IDENTIFIER,
value [0] EXPLICIT ANY DEFINED BY type-id
}

EDIPartyName ::= SEQUENCE {
nameAssigner [0] DirectoryString OPTIONAL,
partyName [1] DirectoryString
}

ORAddress ::= SEQUENCE {
built-in-standard-attributes BuiltInStandardAttributes,
built-in-domain-defined-attributes BuiltInDomainDefinedAttributes OPTIONAL,
-- see also teletex-domain-defined-attributes
extension-attributes ExtensionAttributes OPTIONAL
}

BuiltInStandardAttributes ::= SEQUENCE {
country-name CountryName OPTIONAL,
administration-domain-name AdministrationDomainName OPTIONAL,
network-address [0] IMPLICIT NetworkAddress OPTIONAL,
-- see also extended-network-address
terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL,
private-domain-name [2] PrivateDomainName OPTIONAL,
organization-name [3] IMPLICIT OrganizationName OPTIONAL,
-- see also teletex-organization-name
numeric-user-identifier [4] IMPLICIT NumericUserIdentifier OPTIONAL,
personal-name [5] IMPLICIT PersonalName OPTIONAL,
-- see also teletex-personal-name
organizational-unit-names [6] IMPLICIT OrganizationalUnitNames OPTIONAL
}

CountryName ::= [APPLICATION 1] CHOICE {
x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)),
iso-3166-alpha2-code PrintableString (SIZE (ub-country-name-alpha-length))
}

AdministrationDomainName ::= [APPLICATION 2] CHOICE {
numeric NumericString (SIZE (0..ub-domain-name-length)),
printable PrintableString (SIZE (0..ub-domain-name-length))
}

NetworkAddress ::= X121Address -- see also extended-network-address

X121Address ::= NumericString (SIZE (1..ub-x121-address-length))

TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length))

PrivateDomainName ::= CHOICE {
numeric NumericString (SIZE (1..ub-domain-name-length)),
printable PrintableString (SIZE (1..ub-domain-name-length))
}

OrganizationName ::= PrintableString (SIZE (1..ub-organization-name-length))
-- see also teletex-organization-name

NumericUserIdentifier ::= NumericString (SIZE (1..ub-numeric-user-id-length))

PersonalName ::= SET {
surname [0] IMPLICIT PrintableString (SIZE (1..ub-surname-length)),
given-name [1] IMPLICIT PrintableString (SIZE (1..ub-given-name-length)) OPTIONAL,
initials [2] IMPLICIT PrintableString (SIZE (1..ub-initials-length)) OPTIONAL,
generation-qualifier [3] IMPLICIT PrintableString (SIZE (1..ub-generation-qualifier-length)) OPTIONAL
}
-- see also teletex-personal-name

OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) OF OrganizationalUnitName
-- see also teletex-organizational-unit-names

OrganizationalUnitName ::= PrintableString (SIZE (1..ub-organizational-unit-name-length))

-- Built-in Domain-defined Attributes
BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE (1..ub-domain-defined-attributes) OF BuiltInDomainDefinedAttribute

BuiltInDomainDefinedAttribute ::= SEQUENCE {
type PrintableString (SIZE (1..ub-domain-defined-attribute-type-length)),
value PrintableString (SIZE (1..ub-domain-defined-attribute-value-length))
}

-- Extension Attributes
ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF ExtensionAttribute

ExtensionAttribute ::= SEQUENCE {
extension-attribute-type [0] IMPLICIT INTEGER (0..ub-extension-attributes),
extension-attribute-value [1] ANY DEFINED BY extension-attribute-type
}

-- Extension types and attribute values
common-name INTEGER ::= 1

CommonName ::= PrintableString (SIZE (1..ub-common-name-length))

teletex-common-name INTEGER ::= 2

TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))

teletex-organization-name INTEGER ::= 3

TeletexOrganizationName ::= TeletexString (SIZE (1..ub-organization-name-length))

teletex-personal-name INTEGER ::= 4

TeletexPersonalName ::= SET {
surname [0] IMPLICIT TeletexString (SIZE (1..ub-surname-length)),
given-name [1] IMPLICIT TeletexString (SIZE (1..ub-given-name-length)) OPTIONAL,
initials [2] IMPLICIT TeletexString (SIZE (1..ub-initials-length)) OPTIONAL,
generation-qualifier [3] IMPLICIT TeletexString (SIZE (1..ub-generation-qualifier-length)) OPTIONAL
}

teletex-organizational-unit-names INTEGER ::= 5

TeletexOrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) OF TeletexOrganizationalUnitName

TeletexOrganizationalUnitName ::= TeletexString (SIZE (1..ub-organizational-unit-name-length))

pds-name INTEGER ::= 7

PDSName ::= PrintableString (SIZE (1..ub-pds-name-length))

physical-delivery-country-name INTEGER ::= 8

PhysicalDeliveryCountryName ::= CHOICE {
x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)),
iso-3166-alpha2-code PrintableString (SIZE (ub-country-name-alpha-length))
}

postal-code INTEGER ::= 9

PostalCode ::= CHOICE {
numeric-code NumericString (SIZE (1..ub-postal-code-length)),
printable-code PrintableString (SIZE (1..ub-postal-code-length))
}

physical-delivery-office-name INTEGER ::= 10

PhysicalDeliveryOfficeName ::= PDSParameter

physical-delivery-office-number INTEGER ::= 11

PhysicalDeliveryOfficeNumber ::= PDSParameter

extension-OR-address-components INTEGER ::= 12

ExtensionORAddressComponents ::= PDSParameter

physical-delivery-personal-name INTEGER ::= 13

PhysicalDeliveryPersonalName ::= PDSParameter

physical-delivery-organization-name INTEGER ::= 14

PhysicalDeliveryOrganizationName ::= PDSParameter

extension-physical-delivery-address-components INTEGER ::= 15

ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter

unformatted-postal-address INTEGER ::= 16

UnformattedPostalAddress ::= SET {
printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines) OF PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL,
teletex-string TeletexString (SIZE (1..ub-unformatted-address-length)) OPTIONAL
}

street-address INTEGER ::= 17

StreetAddress ::= PDSParameter

post-office-box-address INTEGER ::= 18

PostOfficeBoxAddress ::= PDSParameter

poste-restante-address INTEGER ::= 19

PosteRestanteAddress ::= PDSParameter

unique-postal-name INTEGER ::= 20

UniquePostalName ::= PDSParameter

local-postal-attributes INTEGER ::= 21

LocalPostalAttributes ::= PDSParameter

PDSParameter ::= SET {
printable-string PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL,
teletex-string TeletexString (SIZE (1..ub-pds-parameter-length)) OPTIONAL
}

extended-network-address INTEGER ::= 22

ExtendedNetworkAddress ::= CHOICE {
e163-4-address SEQUENCE {
number [0] IMPLICIT NumericString (SIZE (1..ub-e163-4-number-length)),
sub-address [1] IMPLICIT NumericString (SIZE (1..ub-e163-4-sub-address-length)) OPTIONAL
},
psap-address [0] IMPLICIT PresentationAddress
}

PresentationAddress ::= SEQUENCE {
pSelector [0] EXPLICIT OCTET STRING OPTIONAL,
sSelector [1] EXPLICIT OCTET STRING OPTIONAL,
tSelector [2] EXPLICIT OCTET STRING OPTIONAL,
nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING
}

terminal-type INTEGER ::= 23

TerminalType ::= INTEGER {
telex (3),
teletex (4),
g3-facsimile (5),
g4-facsimile (6),
ia5-terminal (7),
videotex (8)
} (0..ub-integer-options)

-- Extension Domain-defined Attributes
teletex-domain-defined-attributes INTEGER ::= 6

TeletexDomainDefinedAttributes ::= SEQUENCE SIZE (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute

TeletexDomainDefinedAttribute ::= SEQUENCE {
type TeletexString (SIZE (1..ub-domain-defined-attribute-type-length)),
value TeletexString (SIZE (1..ub-domain-defined-attribute-value-length))
}

-- specifications of Upper Bounds MUST be regarded as mandatory
-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
-- Upper Bounds
-- Upper Bounds
ub-name INTEGER ::= 32768

ub-common-name INTEGER ::= 64

ub-locality-name INTEGER ::= 128

ub-state-name INTEGER ::= 128

ub-organization-name INTEGER ::= 64

ub-organizational-unit-name INTEGER ::= 64

ub-title INTEGER ::= 64

ub-serial-number INTEGER ::= 64

ub-match INTEGER ::= 128

ub-emailaddress-length INTEGER ::= 255

ub-common-name-length INTEGER ::= 64

ub-country-name-alpha-length INTEGER ::= 2

ub-country-name-numeric-length INTEGER ::= 3

ub-domain-defined-attributes INTEGER ::= 4

ub-domain-defined-attribute-type-length INTEGER ::= 8

ub-domain-defined-attribute-value-length INTEGER ::= 128

ub-domain-name-length INTEGER ::= 16

ub-extension-attributes INTEGER ::= 256

ub-e163-4-number-length INTEGER ::= 15

ub-e163-4-sub-address-length INTEGER ::= 40

ub-generation-qualifier-length INTEGER ::= 3

ub-given-name-length INTEGER ::= 16

ub-initials-length INTEGER ::= 5

ub-integer-options INTEGER ::= 256

ub-numeric-user-id-length INTEGER ::= 32

ub-organization-name-length INTEGER ::= 64

ub-organizational-unit-name-length INTEGER ::= 32

ub-organizational-units INTEGER ::= 4

ub-pds-name-length INTEGER ::= 16

ub-pds-parameter-length INTEGER ::= 30

ub-pds-physical-address-lines INTEGER ::= 6

ub-postal-code-length INTEGER ::= 16

ub-pseudonym INTEGER ::= 128

ub-surname-length INTEGER ::= 40

ub-terminal-id-length INTEGER ::= 24

ub-unformatted-address-length INTEGER ::= 180

ub-x121-address-length INTEGER ::= 16
-- Note - upper bounds on string types, such as TeletexString, are
-- measured in characters. Excepting PrintableString or IA5String, a
-- significantly greater number of octets will be required to hold
-- such a value. As a minimum, 16 octets, or twice the specified
-- upper bound, whichever is the larger, should be allowed for
-- TeletexString. For UTF8String or UniversalString at least four
-- times the upper bound should be allowed.

END