move wg keygen to backend
This commit is contained in:
@@ -162,6 +162,8 @@ func (s *ServerService) GenKeypair(keyType string, options string) []string {
|
|||||||
return s.generateTLSKeyPair(options)
|
return s.generateTLSKeyPair(options)
|
||||||
case "reality":
|
case "reality":
|
||||||
return s.generateRealityKeyPair()
|
return s.generateRealityKeyPair()
|
||||||
|
case "wireguard":
|
||||||
|
return generateWireGuardKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{"Failed to generate keypair"}
|
return []string{"Failed to generate keypair"}
|
||||||
@@ -192,3 +194,11 @@ func (s *ServerService) generateRealityKeyPair() []string {
|
|||||||
publicKey := privateKey.PublicKey()
|
publicKey := privateKey.PublicKey()
|
||||||
return []string{"PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey[:]), "PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey[:])}
|
return []string{"PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey[:]), "PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey[:])}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateWireGuardKey() []string {
|
||||||
|
privateKey, err := wgtypes.GeneratePrivateKey()
|
||||||
|
if err != nil {
|
||||||
|
return []string{"Failed to generate wireguard keypair: ", err.Error()}
|
||||||
|
}
|
||||||
|
return []string{"PrivateKey: " + privateKey.String(), "PublicKey: " + privateKey.PublicKey().String()}
|
||||||
|
}
|
||||||
|
|||||||
@@ -109,10 +109,10 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Peer from '@/components/WgPeer.vue'
|
import Peer from '@/components/WgPeer.vue'
|
||||||
import WgUtil from '@/plugins/wgUtil'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['data'],
|
props: ['data'],
|
||||||
|
emits: ["newWgKey"],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
menu: false,
|
menu: false,
|
||||||
@@ -120,14 +120,11 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addPeer() {
|
addPeer() {
|
||||||
this.$props.data.peers.push({
|
this.$props.data.peers.push(this.$props.data.peers[0])
|
||||||
address: '',
|
|
||||||
port: this.$props.data.listen_port
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
newKey() {
|
newKey() {
|
||||||
this.$props.data.private_key = WgUtil.generateKeypair().privateKey
|
this.$emit('newWgKey')
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
optionUdp: {
|
optionUdp: {
|
||||||
|
|||||||
@@ -6,45 +6,22 @@
|
|||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-divider></v-divider>
|
<v-divider></v-divider>
|
||||||
<v-card-text style="padding: 0 16px; overflow-y: scroll;">
|
<v-card-text style="padding: 0 16px; overflow-y: scroll;">
|
||||||
<v-container style="padding: 0;">
|
<v-row>
|
||||||
<v-tabs
|
<v-col cols="12" sm="6" md="4">
|
||||||
v-model="tab"
|
<v-select
|
||||||
align-tabs="center"
|
hide-details
|
||||||
>
|
:label="$t('type')"
|
||||||
<v-tab value="t1">{{ $t('client.basics') }}</v-tab>
|
:items="Object.keys(epTypes).map((key,index) => ({title: key, value: Object.values(epTypes)[index]}))"
|
||||||
<v-tab value="t2">{{ $t('client.external') }}</v-tab>
|
v-model="endpoint.type"
|
||||||
</v-tabs>
|
@update:modelValue="changeType">
|
||||||
<v-window v-model="tab">
|
</v-select>
|
||||||
<v-window-item value="t1">
|
</v-col>
|
||||||
<v-row>
|
<v-col cols="12" sm="6" md="4">
|
||||||
<v-col cols="12" sm="6" md="4">
|
<v-text-field v-model="endpoint.tag" :label="$t('objects.tag')" hide-details></v-text-field>
|
||||||
<v-select
|
</v-col>
|
||||||
hide-details
|
</v-row>
|
||||||
:label="$t('type')"
|
<Wireguard v-if="endpoint.type == epTypes.Wireguard" :data="endpoint" @newWgKey="newWgKey" />
|
||||||
:items="Object.keys(epTypes).map((key,index) => ({title: key, value: Object.values(epTypes)[index]}))"
|
<Dial :dial="endpoint" :outTags="tags" />
|
||||||
v-model="endpoint.type"
|
|
||||||
@update:modelValue="changeType">
|
|
||||||
</v-select>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12" sm="6" md="4">
|
|
||||||
<v-text-field v-model="endpoint.tag" :label="$t('objects.tag')" hide-details></v-text-field>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
<Wireguard v-if="endpoint.type == epTypes.Wireguard" :data="endpoint" />
|
|
||||||
<Dial :dial="endpoint" :outTags="tags" />
|
|
||||||
</v-window-item>
|
|
||||||
<v-window-item value="t2">
|
|
||||||
<v-row>
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-text-field v-model="link" :label="$t('client.external')" hide-details />
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12" align="center">
|
|
||||||
<v-btn hide-details variant="tonal" :loading="loading" @click="linkConvert">{{ $t('submit') }}</v-btn>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-window-item>
|
|
||||||
</v-window>
|
|
||||||
</v-container>
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
@@ -74,7 +51,8 @@ import RandomUtil from '@/plugins/randomUtil'
|
|||||||
import Dial from '@/components/Dial.vue'
|
import Dial from '@/components/Dial.vue'
|
||||||
import Wireguard from '@/components/protocols/Wireguard.vue'
|
import Wireguard from '@/components/protocols/Wireguard.vue'
|
||||||
import HttpUtils from '@/plugins/httputil'
|
import HttpUtils from '@/plugins/httputil'
|
||||||
import WgUtil from '@/plugins/wgUtil'
|
import { push } from 'notivue'
|
||||||
|
import { i18n } from '@/locales'
|
||||||
export default {
|
export default {
|
||||||
props: ['visible', 'data', 'id', 'tags'],
|
props: ['visible', 'data', 'id', 'tags'],
|
||||||
emits: ['close', 'save'],
|
emits: ['close', 'save'],
|
||||||
@@ -89,7 +67,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateData() {
|
async updateData() {
|
||||||
if (this.$props.id > 0) {
|
if (this.$props.id > 0) {
|
||||||
const newData = JSON.parse(this.$props.data)
|
const newData = JSON.parse(this.$props.data)
|
||||||
this.endpoint = createEndpoint(newData.type, newData)
|
this.endpoint = createEndpoint(newData.type, newData)
|
||||||
@@ -102,9 +80,9 @@ export default {
|
|||||||
tag: "wireguard-" + RandomUtil.randomSeq(3),
|
tag: "wireguard-" + RandomUtil.randomSeq(3),
|
||||||
address: ['10.0.0.'+ randomIPoctet.toString() +'/32','fe80::'+ randomIPoctet.toString(16) +'/128'],
|
address: ['10.0.0.'+ randomIPoctet.toString() +'/32','fe80::'+ randomIPoctet.toString(16) +'/128'],
|
||||||
listen_port: port,
|
listen_port: port,
|
||||||
private_key: WgUtil.generateKeypair().privateKey,
|
private_key: (await this.genWgKey()).private_key,
|
||||||
peers: [{
|
peers: [{
|
||||||
public_key: WgUtil.generateKeypair().publicKey,
|
public_key: (await this.genWgKey()).public_key,
|
||||||
allowed_ips: ['0.0.0.0/0', '::/0']
|
allowed_ips: ['0.0.0.0/0', '::/0']
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
@@ -128,17 +106,30 @@ export default {
|
|||||||
this.$emit('save', this.endpoint)
|
this.$emit('save', this.endpoint)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
async linkConvert() {
|
async genWgKey(){
|
||||||
if (this.link.length>0){
|
this.loading = true
|
||||||
this.loading = true
|
const msg = await HttpUtils.get('api/keypairs', { k: "wireguard" })
|
||||||
const msg = await HttpUtils.post('api/linkConvert', { link: this.link })
|
this.loading = false
|
||||||
this.loading = false
|
let result = { private_key: "", public_key: "" }
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
this.endpoint = msg.obj
|
msg.obj.forEach((line:string) => {
|
||||||
this.tab = "t1"
|
if (line.startsWith("PrivateKey")){
|
||||||
this.link = ""
|
result.private_key = line.substring(12)
|
||||||
}
|
}
|
||||||
|
if (line.startsWith("PublicKey")){
|
||||||
|
result.public_key = line.substring(11)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
push.error({
|
||||||
|
message: i18n.global.t('error') + ": " + msg.obj
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
async newWgKey(){
|
||||||
|
const newKeys = await this.genWgKey()
|
||||||
|
this.endpoint.private_key = newKeys.private_key
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
@@ -1,188 +0,0 @@
|
|||||||
const WgUtil = {
|
|
||||||
gf(init?: Float64Array): Float64Array {
|
|
||||||
var r = new Float64Array(16)
|
|
||||||
if (init) {
|
|
||||||
for (var i = 0; i < init.length; ++i)
|
|
||||||
r[i] = init[i]
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
},
|
|
||||||
|
|
||||||
pack(o: Float64Array, n: Float64Array): Float64Array {
|
|
||||||
var b, m = this.gf(), t = this.gf()
|
|
||||||
for (var i = 0; i < 16; ++i)
|
|
||||||
t[i] = n[i]
|
|
||||||
this.carry(t)
|
|
||||||
this.carry(t)
|
|
||||||
this.carry(t)
|
|
||||||
for (var j = 0; j < 2; ++j) {
|
|
||||||
m[0] = t[0] - 0xffed
|
|
||||||
for (var i = 1; i < 15; ++i) {
|
|
||||||
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1)
|
|
||||||
m[i - 1] &= 0xffff
|
|
||||||
}
|
|
||||||
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1)
|
|
||||||
b = (m[15] >> 16) & 1
|
|
||||||
m[14] &= 0xffff
|
|
||||||
this.cswap(t, m, 1 - b)
|
|
||||||
}
|
|
||||||
for (var i = 0; i < 16; ++i) {
|
|
||||||
o[2 * i] = t[i] & 0xff
|
|
||||||
o[2 * i + 1] = t[i] >> 8
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
carry(o: Float64Array) {
|
|
||||||
var c
|
|
||||||
for (var i = 0; i < 16; ++i) {
|
|
||||||
o[(i + 1) % 16] += (i < 15 ? 1 : 38) * Math.floor(o[i] / 65536)
|
|
||||||
o[i] &= 0xffff
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
cswap(p: Float64Array, q: Float64Array, b: number) {
|
|
||||||
var t, c = ~(b - 1)
|
|
||||||
for (var i = 0; i < 16; ++i) {
|
|
||||||
t = c & (p[i] ^ q[i])
|
|
||||||
p[i] ^= t
|
|
||||||
q[i] ^= t
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
add(o: Float64Array, a: Float64Array, b: Float64Array) {
|
|
||||||
for (var i = 0; i < 16; ++i)
|
|
||||||
o[i] = (a[i] + b[i]) | 0
|
|
||||||
},
|
|
||||||
|
|
||||||
subtract(o: Float64Array, a: Float64Array, b: Float64Array) {
|
|
||||||
for (var i = 0; i < 16; ++i)
|
|
||||||
o[i] = (a[i] - b[i]) | 0
|
|
||||||
},
|
|
||||||
|
|
||||||
multmod(o: Float64Array, a: Float64Array, b: Float64Array) {
|
|
||||||
var t = new Float64Array(31)
|
|
||||||
for (var i = 0; i < 16; ++i) {
|
|
||||||
for (var j = 0; j < 16; ++j)
|
|
||||||
t[i + j] += a[i] * b[j]
|
|
||||||
}
|
|
||||||
for (var i = 0; i < 15; ++i)
|
|
||||||
t[i] += 38 * t[i + 16]
|
|
||||||
for (var i = 0; i < 16; ++i)
|
|
||||||
o[i] = t[i]
|
|
||||||
this.carry(o)
|
|
||||||
this.carry(o)
|
|
||||||
},
|
|
||||||
|
|
||||||
invert(o: Float64Array, i: Float64Array) {
|
|
||||||
var c = this.gf()
|
|
||||||
for (var a = 0; a < 16; ++a)
|
|
||||||
c[a] = i[a]
|
|
||||||
for (var a = 253; a >= 0; --a) {
|
|
||||||
this.multmod(c, c, c)
|
|
||||||
if (a !== 2 && a !== 4)
|
|
||||||
this.multmod(c, c, i)
|
|
||||||
}
|
|
||||||
for (var a = 0; a < 16; ++a)
|
|
||||||
o[a] = c[a]
|
|
||||||
},
|
|
||||||
|
|
||||||
clamp(z) {
|
|
||||||
z[31] = (z[31] & 127) | 64
|
|
||||||
z[0] &= 248
|
|
||||||
},
|
|
||||||
|
|
||||||
generatePublicKey(privateKey: Uint8Array): Uint8Array {
|
|
||||||
var r, z = new Uint8Array(32)
|
|
||||||
var a = this.gf([1]),
|
|
||||||
b = this.gf([9]),
|
|
||||||
c = this.gf(),
|
|
||||||
d = this.gf([1]),
|
|
||||||
e = this.gf(),
|
|
||||||
f = this.gf(),
|
|
||||||
_121665 = this.gf([0xdb41, 1]),
|
|
||||||
_9 = this.gf([9])
|
|
||||||
for (var i = 0; i < 32; ++i)
|
|
||||||
z[i] = privateKey[i]
|
|
||||||
this.clamp(z)
|
|
||||||
for (var i = 254; i >= 0; --i) {
|
|
||||||
r = (z[i >>> 3] >>> (i & 7)) & 1
|
|
||||||
this.cswap(a, b, r)
|
|
||||||
this.cswap(c, d, r)
|
|
||||||
this.add(e, a, c)
|
|
||||||
this.subtract(a, a, c)
|
|
||||||
this.add(c, b, d)
|
|
||||||
this.subtract(b, b, d)
|
|
||||||
this.multmod(d, e, e)
|
|
||||||
this.multmod(f, a, a)
|
|
||||||
this.multmod(a, c, a)
|
|
||||||
this.multmod(c, b, e)
|
|
||||||
this.add(e, a, c)
|
|
||||||
this.subtract(a, a, c)
|
|
||||||
this.multmod(b, a, a)
|
|
||||||
this.subtract(c, d, f)
|
|
||||||
this.multmod(a, c, _121665)
|
|
||||||
this.add(a, a, d)
|
|
||||||
this.multmod(c, c, a)
|
|
||||||
this.multmod(a, d, f)
|
|
||||||
this.multmod(d, b, _9)
|
|
||||||
this.multmod(b, e, e)
|
|
||||||
this.cswap(a, b, r)
|
|
||||||
this.cswap(c, d, r)
|
|
||||||
}
|
|
||||||
this.invert(c, c)
|
|
||||||
this.multmod(a, a, c)
|
|
||||||
this.pack(z, a)
|
|
||||||
return z
|
|
||||||
},
|
|
||||||
|
|
||||||
generatePresharedKey(): Uint8Array {
|
|
||||||
var privateKey = new Uint8Array(32)
|
|
||||||
window.crypto.getRandomValues(privateKey)
|
|
||||||
return privateKey
|
|
||||||
},
|
|
||||||
|
|
||||||
generatePrivateKey(): Uint8Array {
|
|
||||||
var privateKey = this.generatePresharedKey()
|
|
||||||
this.clamp(privateKey)
|
|
||||||
return privateKey
|
|
||||||
},
|
|
||||||
|
|
||||||
encodeBase64(dest: Uint8Array, src: Uint8Array) {
|
|
||||||
var input = Uint8Array.from([(src[0] >> 2) & 63, ((src[0] << 4) | (src[1] >> 4)) & 63, ((src[1] << 2) | (src[2] >> 6)) & 63, src[2] & 63])
|
|
||||||
for (var i = 0; i < 4; ++i)
|
|
||||||
dest[i] = input[i] + 65 +
|
|
||||||
(((25 - input[i]) >> 8) & 6) -
|
|
||||||
(((51 - input[i]) >> 8) & 75) -
|
|
||||||
(((61 - input[i]) >> 8) & 15) +
|
|
||||||
(((62 - input[i]) >> 8) & 3)
|
|
||||||
},
|
|
||||||
|
|
||||||
keyToBase64(key: Uint8Array): string {
|
|
||||||
var i, base64 = new Uint8Array(44)
|
|
||||||
for (i = 0; i < 32 / 3; ++i)
|
|
||||||
this.encodeBase64(base64.subarray(i * 4), key.subarray(i * 3))
|
|
||||||
this.encodeBase64(base64.subarray(i * 4), Uint8Array.from([key[i * 3 + 0], key[i * 3 + 1], 0]))
|
|
||||||
base64[43] = 61
|
|
||||||
return String.fromCharCode.apply(null, base64)
|
|
||||||
},
|
|
||||||
|
|
||||||
keyFromBase64(encoded: string): Uint8Array {
|
|
||||||
const binaryStr = atob(encoded)
|
|
||||||
const bytes = new Uint8Array(binaryStr.length)
|
|
||||||
for (let i = 0; i < binaryStr.length; i++) {
|
|
||||||
bytes[i] = binaryStr.charCodeAt(i)
|
|
||||||
}
|
|
||||||
return bytes
|
|
||||||
},
|
|
||||||
|
|
||||||
generateKeypair(secretKey?: string ='') {
|
|
||||||
var privateKey = secretKey.length>0 ? this.keyFromBase64(secretKey) : this.generatePrivateKey()
|
|
||||||
var publicKey = this.generatePublicKey(privateKey)
|
|
||||||
return {
|
|
||||||
publicKey: this.keyToBase64(publicKey),
|
|
||||||
privateKey: secretKey.length>0 ? secretKey : this.keyToBase64(privateKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default WgUtil
|
|
||||||
@@ -6,8 +6,6 @@ export const EpTypes = {
|
|||||||
|
|
||||||
type EpType = typeof EpTypes[keyof typeof EpTypes]
|
type EpType = typeof EpTypes[keyof typeof EpTypes]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface EndpointBasics {
|
interface EndpointBasics {
|
||||||
id: number
|
id: number
|
||||||
type: EpType
|
type: EpType
|
||||||
|
|||||||
Reference in New Issue
Block a user