unify line endings
[GitHub/Stricted/Domain-Control-Panel.git] / lib / util / DNSSECUtil.class.php
CommitLineData
daff88c0
S
1<?php
2namespace dns\util;
3
4/**
5 * @author Jan Altensen (Stricted)
6 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
7 * @copyright 2015 Jan Altensen (Stricted)
8 */
9class DNSSECUtil {
f709187e
S
10 // see: http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
11 public static $availableAlgorithm = array(3, 5, 6, 7, 8, 10, 12, 13, 14);
daff88c0 12
a760846b
S
13 /**
14 * calculate the DS record for parent zone
15 *
16 * @param string $owner
17 * @param string $algorithm
18 * @param string $publicKey
19 * @return array
20 */
8a0590a6
S
21 public static function calculateDS ($owner, $algorithm, $publicKey) {
22 $owner = self::convertOwner($owner);
daff88c0
S
23 $flags = '0101';
24 $protocol = '03';
25 $algorithm = '0'.dechex($algorithm);
26 $publicKey = bin2hex(base64_decode($publicKey));
27
28 $string = hex2bin($owner.$flags.$protocol.$algorithm.$publicKey);
29
6a2c67f1
S
30 $sha1 = strtoupper(sha1($string));
31 $sha256 = strtoupper(hash('sha256', $string));
daff88c0
S
32
33 return array('sha1' => $sha1, 'sha256' => $sha256);
34 }
35
a760846b
S
36 /**
37 * convert the domain name to HEX
38 *
39 * @param string $owner
40 * @return string
41 */
6a2c67f1 42 public static function convertOwner ($owner) {
f709187e
S
43 if (substr($owner, -1) == '.') {
44 $owner = substr($owner, 0, -1);
daff88c0
S
45 }
46
f709187e 47 $return = '';
daff88c0 48
f709187e
S
49 $parts = explode(".", $owner);
50 foreach ($parts as $part) {
51 $len = dechex(strlen($part));
52 $return .= str_repeat('0', 2 - strlen($len)).$len;
53 $part = str_split($part);
54 for ($i = 0; $i < count($part); $i++) {
55 $byte = strtoupper(dechex(ord($part[$i])));
56 $byte = str_repeat('0', 2 - strlen($byte)).$byte;
57 $return .= $byte;
58 }
daff88c0
S
59 }
60
61 $return .= '00';
62
63 return $return;
64 }
8a0590a6 65
a760846b
S
66 /**
67 * validate DNSSEC public key
68 *
69 * @param string $content
70 * @return boolean
71 */
f709187e 72 public static function validatePublicKey ($content) {
8e9fc9e0
S
73 // unify newlines
74 $content = preg_replace("/(\r\n)|(\r)/", "\n", $content);
75
8a0590a6
S
76 $pattern = "; This is a (key|zone)-signing key, keyid (?P<keyid>[0-9]+), for (?P<domain>[\s\S]+)\.\n";
77 $pattern .= "; Created: (?P<created>[0-9]+) \(([a-z0-9: ]+)\)\n";
78 $pattern .= "; Publish: (?P<publish>[0-9]+) \(([a-z0-9: ]+)\)\n";
79 $pattern .= "; Activate: (?P<activate>[0-9]+) \(([a-z0-9: ]+)\)\n";
6a2c67f1 80 $pattern .= "([\s\S]+). IN DNSKEY 25(6|7) 3 (?P<algorithm>[0-9]+) (?P<key>[\s\S]+)(\n)?";
8a0590a6
S
81 preg_match('/'.$pattern.'/i', $content, $matches);
82 if (!empty($matches)) {
f709187e 83 if (!in_array($matches['algorithm'], self::$availableAlgorithm)) {
45c89c08
S
84 return false;
85 }
86
8a0590a6
S
87 $data = explode(' ', $matches['key']);
88 foreach ($data as $d) {
89 if (base64_encode(base64_decode($d, true)) !== $d) {
90 return false;
91 }
92 }
93 }
94 else {
95 return false;
96 }
97
98 return true;
99 }
100
a760846b
S
101 /**
102 * validate DNSSEC private key
103 *
104 * @param string $content
105 * @return boolean
106 */
8a0590a6 107 public static function validatePrivateKey ($content) {
8e9fc9e0
S
108 // unify newlines
109 $content = preg_replace("/(\r\n)|(\r)/", "\n", $content);
110
8a0590a6
S
111 $pattern = "Private-key-format: v([0-9a-z.]+)\n";
112 $pattern .= "Algorithm: (?P<algorithm>[0-9]+) \(([0-9a-z\-]+)\)\n";
113 $pattern .= "Modulus: (?P<modulus>[\s\S]+)\n";
114 $pattern .= "PublicExponent: (?P<publicexponent>[\s\S]+)\n";
f709187e 115 $pattern .= "PrivateExponent: (?P<privatexponent>[\s\S]+)\n";
8a0590a6
S
116 $pattern .= "Prime1: (?P<prime1>[\s\S]+)\n";
117 $pattern .= "Prime2: (?P<prime2>[\s\S]+)\n";
118 $pattern .= "Exponent1: (?P<exponent1>[\s\S]+)\n";
119 $pattern .= "Exponent2: (?P<exponent2>[\s\S]+)\n";
120 $pattern .= "Coefficient: (?P<coefficient>[\s\S]+)\n";
121 $pattern .= "Created: (?P<created>[0-9]+)\n";
122 $pattern .= "Publish: (?P<publish>[0-9]+)\n";
6a2c67f1 123 $pattern .= "Activate: (?P<activate>[0-9]+)(\n)?";
a760846b 124
8a0590a6
S
125 preg_match('/'.$pattern.'/i', $content, $matches);
126 if (!empty($matches)) {
f709187e 127 if (!in_array($matches['algorithm'], self::$availableAlgorithm)) {
45c89c08
S
128 return false;
129 }
130 else if (base64_encode(base64_decode($matches['modulus'], true)) !== $matches['modulus']) {
131 return false;
132 }
133 else if (base64_encode(base64_decode($matches['publicexponent'], true)) !== $matches['publicexponent']) {
134 return false;
135 }
f709187e
S
136 else if (base64_encode(base64_decode($matches['privatexponent'], true)) !== $matches['privatexponent']) {
137 return false;
138 }
45c89c08
S
139 else if (base64_encode(base64_decode($matches['prime1'], true)) !== $matches['prime1']) {
140 return false;
141 }
142 else if (base64_encode(base64_decode($matches['prime2'], true)) !== $matches['prime2']) {
143 return false;
144 }
145 else if (base64_encode(base64_decode($matches['exponent1'], true)) !== $matches['exponent1']) {
146 return false;
147 }
148 else if (base64_encode(base64_decode($matches['exponent2'], true)) !== $matches['exponent2']) {
149 return false;
150 }
151 else if (base64_encode(base64_decode($matches['coefficient'], true)) !== $matches['coefficient']) {
152 return false;
153 }
8a0590a6
S
154 }
155 else {
156 return false;
157 }
158
159 return true;
160 }
daff88c0 161}