improve convertOwner method
[GitHub/Stricted/Domain-Control-Panel.git] / lib / util / DNSSECUtil.class.php
1 <?php
2 namespace 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 */
9 class DNSSECUtil {
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);
12
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 */
21 public static function calculateDS ($owner, $algorithm, $publicKey) {
22 $owner = self::convertOwner($owner);
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
30 $sha1 = strtoupper(sha1($string));
31 $sha256 = strtoupper(hash('sha256', $string));
32
33 return array('sha1' => $sha1, 'sha256' => $sha256);
34 }
35
36 /**
37 * convert the domain name to HEX
38 *
39 * @param string $owner
40 * @return string
41 */
42 public static function convertOwner ($owner) {
43 if (substr($owner, -1) == '.') {
44 $owner = substr($owner, 0, -1);
45 }
46
47 $return = '';
48
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 }
59 }
60
61 $return .= '00';
62
63 return $return;
64 }
65
66 /**
67 * validate DNSSEC public key
68 *
69 * @param string $content
70 * @return boolean
71 */
72 public static function validatePublicKey ($content) {
73 $pattern = "; This is a (key|zone)-signing key, keyid (?P<keyid>[0-9]+), for (?P<domain>[\s\S]+)\.\n";
74 $pattern .= "; Created: (?P<created>[0-9]+) \(([a-z0-9: ]+)\)\n";
75 $pattern .= "; Publish: (?P<publish>[0-9]+) \(([a-z0-9: ]+)\)\n";
76 $pattern .= "; Activate: (?P<activate>[0-9]+) \(([a-z0-9: ]+)\)\n";
77 $pattern .= "([\s\S]+). IN DNSKEY 25(6|7) 3 (?P<algorithm>[0-9]+) (?P<key>[\s\S]+)(\n)?";
78 preg_match('/'.$pattern.'/i', $content, $matches);
79 if (!empty($matches)) {
80 if (!in_array($matches['algorithm'], self::$availableAlgorithm)) {
81 return false;
82 }
83
84 $data = explode(' ', $matches['key']);
85 foreach ($data as $d) {
86 if (base64_encode(base64_decode($d, true)) !== $d) {
87 return false;
88 }
89 }
90 }
91 else {
92 return false;
93 }
94
95 return true;
96 }
97
98 /**
99 * validate DNSSEC private key
100 *
101 * @param string $content
102 * @return boolean
103 */
104 public static function validatePrivateKey ($content) {
105 $pattern = "Private-key-format: v([0-9a-z.]+)\n";
106 $pattern .= "Algorithm: (?P<algorithm>[0-9]+) \(([0-9a-z\-]+)\)\n";
107 $pattern .= "Modulus: (?P<modulus>[\s\S]+)\n";
108 $pattern .= "PublicExponent: (?P<publicexponent>[\s\S]+)\n";
109 $pattern .= "PrivateExponent: (?P<privatexponent>[\s\S]+)\n";
110 $pattern .= "Prime1: (?P<prime1>[\s\S]+)\n";
111 $pattern .= "Prime2: (?P<prime2>[\s\S]+)\n";
112 $pattern .= "Exponent1: (?P<exponent1>[\s\S]+)\n";
113 $pattern .= "Exponent2: (?P<exponent2>[\s\S]+)\n";
114 $pattern .= "Coefficient: (?P<coefficient>[\s\S]+)\n";
115 $pattern .= "Created: (?P<created>[0-9]+)\n";
116 $pattern .= "Publish: (?P<publish>[0-9]+)\n";
117 $pattern .= "Activate: (?P<activate>[0-9]+)(\n)?";
118
119 preg_match('/'.$pattern.'/i', $content, $matches);
120 if (!empty($matches)) {
121 if (!in_array($matches['algorithm'], self::$availableAlgorithm)) {
122 return false;
123 }
124 else if (base64_encode(base64_decode($matches['modulus'], true)) !== $matches['modulus']) {
125 return false;
126 }
127 else if (base64_encode(base64_decode($matches['publicexponent'], true)) !== $matches['publicexponent']) {
128 return false;
129 }
130 else if (base64_encode(base64_decode($matches['privatexponent'], true)) !== $matches['privatexponent']) {
131 return false;
132 }
133 else if (base64_encode(base64_decode($matches['prime1'], true)) !== $matches['prime1']) {
134 return false;
135 }
136 else if (base64_encode(base64_decode($matches['prime2'], true)) !== $matches['prime2']) {
137 return false;
138 }
139 else if (base64_encode(base64_decode($matches['exponent1'], true)) !== $matches['exponent1']) {
140 return false;
141 }
142 else if (base64_encode(base64_decode($matches['exponent2'], true)) !== $matches['exponent2']) {
143 return false;
144 }
145 else if (base64_encode(base64_decode($matches['coefficient'], true)) !== $matches['coefficient']) {
146 return false;
147 }
148 }
149 else {
150 return false;
151 }
152
153 return true;
154 }
155 }