Skip to content

Commit 1331b34

Browse files
committed
Merge branch 'up/feat/seip-auth-tester' into chore/all-my-stuffs
2 parents def1f32 + 362434c commit 1331b34

File tree

7 files changed

+139
-1
lines changed

7 files changed

+139
-1
lines changed

locales/en.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,4 +457,13 @@ tools:
457457

458458
unicode-to-java-entities:
459459
title: Unicode Characters to Java Entities Converter
460-
description: Unicode Characters to Java Entities Converter and vice-versa
460+
description: Unicode Characters to Java Entities Converter and vice-versa
461+
462+
sip-auth:
463+
password: SIP password
464+
password-tips: Enter a password...
465+
message: SIP message
466+
message-tips: Paste your SIP message here...
467+
result: Result
468+
sucess: Sucess
469+
failure: Failure

locales/zh.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,3 +404,13 @@ tools:
404404
text-to-binary:
405405
title: 文本到 ASCII 二进制
406406
description: 将文本转换为其 ASCII 二进制表示形式,反之亦然。
407+
sip-auth:
408+
title: SIP 认证校验
409+
description: 这个工具能够帮你验证 SIP 授权头。该工具所有运算过程都在浏览器中进行,并不会通过网络传输敏感信息,所以请放心使用。
410+
password: SIP 密码
411+
password-tips: 输入密码...
412+
message: SIP 消息文本
413+
message-tips: 在此处粘贴您的 SIP 消息...
414+
result: 检测结果
415+
sucess: 成功
416+
failure: 失败

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ import { tool as ttlCalculator } from './ttl-calculator';
118118
import { tool as unicodeFormatter } from './unicode-formatter';
119119
import { tool as raidCalculator } from './raid-calculator';
120120
import { tool as nanoidGenerator } from './nanoid-generator';
121+
import { tool as sipAuth } from './sip-auth';
121122

122123
import { tool as asciiTextDrawer } from './ascii-text-drawer';
123124

@@ -484,6 +485,7 @@ export const toolsByCategory: ToolCategory[] = [
484485
option43Generator,
485486
portNumbers,
486487
raidCalculator,
488+
sipAuth,
487489
],
488490
},
489491
{

src/tools/sip-auth/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ShieldCheck } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'SIP Authorization',
6+
path: '/sip-auth',
7+
description: 'This tool helps you to verify the SIP authorization header. The tool performs all calculations in the browser and does not transmit sensitive information over the network, so feel free to use it.',
8+
keywords: ['sip', 'authorization'],
9+
component: () => import('./sip-auth.vue'),
10+
icon: ShieldCheck,
11+
createdAt: new Date('2024-04-11'),
12+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { getAuthHeaderCheckResult } from './sip-auth.service';
3+
4+
const message = `REGISTER sip:172.21.169.226 SIP/2.0
5+
Via: SIP/2.0/UDP 172.21.160.1:64712;rport;branch=z9hG4bKPja70ba2f5f4464081a3925196ebd4e7f9
6+
Max-Forwards: 70
7+
From: <sip:[email protected]>;tag=8db088f1039e49b691e53e5f172ace98
8+
9+
Call-ID: be95702faee84a8ebc8ccf94c5ca5492
10+
CSeq: 37808 REGISTER
11+
User-Agent: MicroSIP/3.21.3
12+
Contact: <sip:[email protected]:64712;ob>
13+
Expires: 300
14+
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
15+
Authorization: Digest username="1000", realm="172.21.169.226", nonce="d99a372c-340a-4ec9-91ed-53ad8f318ae0", uri="sip:172.21.169.226", response="7bdeb758d949a3c5e8d125fafbac1d5e", algorit=MD5, cnonce="3a8c445fb7ff48aeb8c422b00afaaddc", qop=auth, nc=00000001
16+
Content-Length: 0`;
17+
18+
describe('getAuthHeaderCheckResult', () => {
19+
it('should return "check success" for valid authentication', () => {
20+
const password = '1234';
21+
const result = getAuthHeaderCheckResult({ message, password });
22+
expect(result).toBe(true);
23+
});
24+
25+
it('should return "check failed" for invalid authentication', () => {
26+
const password = '12345';
27+
const result = getAuthHeaderCheckResult({ message, password });
28+
expect(result).toBe(false);
29+
});
30+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { MD5 } from 'crypto-js';
2+
3+
export { getAuthHeaderCheckResult };
4+
5+
function getAuthHeaderCheckResult({ message, password }: { message: string; password: string }) {
6+
let calculatedHash;
7+
const method = extractComponent('^([A-Z]+) sip', message);
8+
const username = extractComponent('username="([^"]+)"', message);
9+
const realm = extractComponent('realm="([^"]+)"', message);
10+
const uri = extractComponent('uri="([^"]+)"', message);
11+
const nonce = extractComponent('[^c]nonce="([^"]+)"', message);
12+
const cnonce = extractComponent('cnonce="([^"]+)"', message);
13+
const nc = extractComponent('nc=([0-9a-f]+)', message);
14+
const qop = extractComponent('qop="?(auth|auth-int)"?', message);
15+
const response = extractComponent('response="([^"]+)"', message);
16+
const ha1 = MD5(`${username}:${realm}:${password}`).toString();
17+
const ha2 = MD5(`${method}:${uri}`).toString();
18+
if (qop.toLowerCase() === 'auth') {
19+
calculatedHash = MD5(`${ha1}:${nonce}:${nc}:${cnonce}:${qop}:${ha2}`).toString();
20+
}
21+
else {
22+
calculatedHash = MD5(`${ha1}:${nonce}:${cnonce}`).toString();
23+
}
24+
return (response === calculatedHash);
25+
}
26+
27+
function extractComponent(regex: string, source: string): string {
28+
const processor = new RegExp(regex, 'i');
29+
const matchResult = processor.exec(source);
30+
if (matchResult !== null && matchResult.length > 1) {
31+
return matchResult[1];
32+
}
33+
else {
34+
return 'Not Found';
35+
}
36+
}

src/tools/sip-auth/sip-auth.vue

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<script setup lang="ts">
2+
import { getAuthHeaderCheckResult } from './sip-auth.service';
3+
4+
const password = ref('');
5+
const { t } = useI18n();
6+
7+
function transformer(value: string) {
8+
if (value !== '' && password.value !== '') {
9+
const Result = getAuthHeaderCheckResult({ message: value, password: password.value });
10+
if (Result) {
11+
return t('tools.sip-auth.sucess');
12+
}
13+
else {
14+
return t('tools.sip-auth.failure');
15+
// return `11 calculatedHash: ${calculatedHash}, response: ${response}`;
16+
}
17+
}
18+
}
19+
</script>
20+
21+
<template>
22+
<div flex flex-col gap-4>
23+
<c-input-text
24+
v-model:value="password"
25+
type="password"
26+
:placeholder="$t('tools.sip-auth.password-tips')"
27+
autofocus
28+
raw-text
29+
:label="$t('tools.sip-auth.password')"
30+
/>
31+
<format-transformer
32+
:input-label="$t('tools.sip-auth.message')"
33+
:input-placeholder="$t('tools.sip-auth.message-tips')"
34+
:output-label="$t('tools.sip-auth.result')"
35+
:transformer="transformer"
36+
autosize
37+
/>
38+
</div>
39+
</template>

0 commit comments

Comments
 (0)