-
Notifications
You must be signed in to change notification settings - Fork 0
/
doc.go
121 lines (83 loc) · 4.32 KB
/
doc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//go:generate go-bindata -o cmd/bindata.go -ignore generator.*|.*_test.go -pkg cmd -prefix internal ./internal
// Copyright ©2016 Markus W Mahlberg <[email protected]>
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
The package PKV provides a command line tool to generate,
use and manage product keys utilizing Partial Key Verification scheme.
Furthermore, it generates code to verify those product keys.
A product key is composed of a [5]byte seed, four [2]byte key parts and a [7]byte checksum
of the seed and the key parts.
The seed is used to uniquely identify a key. This is important as keys can be blacklisted.
Of the four key parts, only one is checked by the software utilizing the partial key
verification scheme at a time. The idea behind this is that even when a cracker manages
to create a key generator for that key part, you can simply switch to checking another key
part in a future version of the software. So the key generator will not be able to generate keys
passing the verification process any more but the product keys you issued retain their
validity.
The Partial Key verification scheme is described in detail at Brandon Stagg's Blog (see below).
Note that you do not need and should not import the package. The command line utility "pkv"
will help you to create keys and generate the according validation code for your software.
Using the pkv utility is pretty straightforward. First, you need to install it
$ go get -u "gopkg.in/mwmahlberg/pkv.v1"
Then, you need to create the secret matrix and store it in a file. The secret matrix is
what makes the product keys you generate unique. You should never ever make this publicly
available.
Of course, the pkv utility generates this file for you:
$ pkv.v1 init -f /path/to/save/dir/pkv.key
This will generate a random matrix using the "cryptographically secure pseudorandom number generator"
from "crypto/rand". It is stored in GOB format (see below).
Keep this file secure and safe at all times. It is used to generate the product keys.
The next step is to generate a key. A key is uniquely identified by a seed. So your seed should be
unqiue per customer. This in turn means that you need to keep track of the seeds you use.
Currently, you can only generate 2097151 different keys because of a limitation to 32bit unsigned integers.
Lifting this limitation is on the roadmap, but slightly less than 2.1 million keys should be sufficient for now.
Lastly you must generate the code for verifying the product keys:
$ cd $GOPATH/src/you.com/cool
$ pkv.v1 gencode -f /path/to/pkv.key -k 1
The "-k" flag denotes the key part you want to check. your directory should look like this:
example.com/
└── cool
└── internal
├── pkvcheck.go
└── pkvtools.go
The code generated needs to be imported and provides several functions,
but only two are of importance, as shown below:
package main
import (
"example.com/cool/internal"
)
func main() {
var key string = getKeyFromSomewhere()
var blacklist []uint64 = loadBlacklistFromServer()
if err := internal.KeyChecksum(key); err != nil {
panic(err)
}
if err := internal.Key(key, blacklist); err != nil {
panic(err)
}
}
The KeyChecksum(string) function provides easy checking for the general correctnes of the product key.
You might want to use it to check wether the key was entered correctly.
Note that this does not provide any security, as a valid checksum is relatively easy to compute.
The Key(key,blacklist) actually does the product key verification.
Now you are done and have a product key generator and validation!
Further reading:
Partial Key Verification
http://www.brandonstaggs.com/2007/07/26/implementing-a-partial-serial-number-verification-system-in-delphi/
GOB format
http://blog.golang.org/gobs-of-data
https://golang.org/pkg/encoding/gob/
*/
package main