Skip to content

Commit fee92c4

Browse files
authored
Stable v1.0 | Add GOST 34.10-2001 support
1 parent 4b60b62 commit fee92c4

2 files changed

Lines changed: 61 additions & 2 deletions

File tree

main.go

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"bufio"
55
"encoding/asn1"
6+
"encoding/binary"
67
"encoding/hex"
78
"encoding/pem"
89
"fmt"
@@ -63,6 +64,31 @@ func costyl(val []byte) []byte {
6364
return decodeHex("30" + fmt.Sprintf("%x", len(tmp)) + hex.EncodeToString(tmp))
6465
}
6566

67+
// CryptoPro KEK diversification algorithm, RFC 4757 section 6.5
68+
func cp_kek_diversify(kek []byte, ukm []byte) []byte {
69+
out := make([]byte, len(kek))
70+
copy(out, kek)
71+
72+
for i := 0; i < 8; i++ {
73+
s1, s2 := 0, 0
74+
for j := 0; j < 8; j++ {
75+
k := int32(binary.LittleEndian.Uint32(out[j*4 : j*4+4]))
76+
if (ukm[i] >> uint(j) & 1) != 0 {
77+
s1 += int(k)
78+
} else {
79+
s2 += int(k)
80+
}
81+
}
82+
iv := make([]byte, 8)
83+
binary.LittleEndian.PutUint32(iv[:4], uint32(s1%(1<<32)))
84+
binary.LittleEndian.PutUint32(iv[4:], uint32(s2%(1<<32)))
85+
cipher := gost28147.NewCipher(out, &gost28147.SboxIdGost2814789CryptoProAParamSet).NewCFBEncrypter(iv)
86+
cipher.XORKeyStream(out, out)
87+
}
88+
89+
return out
90+
}
91+
6692
func main() {
6793
if len(os.Args) < 2 {
6894
fmt.Println("Как использовать: ./program <файл PFX>")
@@ -75,7 +101,11 @@ func main() {
75101
PASS := string(password)
76102
bin, _ := readBinFile(os.Args[1])
77103
pfx, _ := getKeybags(bin)
104+
count := 0
78105
for _, keybag := range pfx {
106+
if count == 1 {
107+
break
108+
}
79109
var info pbeInfo
80110
asn1.Unmarshal(keybag.Value.Bytes, &info)
81111
ROUNDS := info.Header.Parameters.Rounds
@@ -106,6 +136,9 @@ func main() {
106136
if algtype == "42aa" {
107137
algooid = asn1.ObjectIdentifier([]int{1, 2, 643, 7, 1, 1, 1, 2})
108138
}
139+
if algtype == "24aa" {
140+
algooid = asn1.ObjectIdentifier([]int{1, 2, 643, 2, 2, 19})
141+
}
109142

110143
var oids exportKeyBlobOids
111144

@@ -118,6 +151,31 @@ func main() {
118151
KEKe := kdfer.Derive(nil, decodeHex("26BDB878"), UKM)
119152
fmt.Println(" KEKE = " + hex.EncodeToString(KEKe))
120153
switch algtype {
154+
case "24aa":
155+
Ks := make([]byte, len(ENC))
156+
cipher := gost28147.NewCipher(cp_kek_diversify(KEY, UKM), &gost28147.SboxIdGost2814789CryptoProAParamSet)
157+
fe := cipher.NewECBDecrypter()
158+
fe.CryptBlocks(Ks, ENC)
159+
fmt.Println(" K = " + hex.EncodeToString(Ks))
160+
var pkey privateKey
161+
pkey.PrivateKey = Ks
162+
pkey.Algorithm.Value = algooid
163+
pkey.Algorithm.Parameters.Curve = oids.Value.Curve
164+
pkey.Algorithm.Parameters.Digest = oids.Value.Digest
165+
result, err := asn1.Marshal(pkey)
166+
if err != nil {
167+
panic("Ks2pem: " + err.Error())
168+
}
169+
block := &pem.Block{
170+
Type: "PRIVATE KEY",
171+
Bytes: result,
172+
}
173+
uid := uuid.NewString()
174+
file, _ := os.Create("exported_" + uid + ".pem")
175+
defer file.Close()
176+
pem.Encode(file, block)
177+
fmt.Println("Сохранено в exported_" + uid + ".pem")
178+
121179
case "46aa", "42aa":
122180
Ks := make([]byte, len(ENC))
123181
cipher := gost28147.NewCipher(KEKe, &gost28147.SboxIdGost2814789CryptoProAParamSet)
@@ -143,7 +201,8 @@ func main() {
143201
pem.Encode(file, block)
144202
fmt.Println("Сохранено в exported_" + uid + ".pem")
145203
default:
146-
panic("unwrap: not supported key algorithm. It must be GOST 34.10-2012_256 or 34.10-2012_512")
204+
panic("unwrap: not supported key algorithm. It must be GOST 34.10-2012_256 or 34.10-2012_512 (" + algtype + ")")
147205
}
206+
count++
148207
}
149208
}

types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type exportKeyBlob struct {
3838
Enc []byte
3939
Mac []byte
4040
}
41-
Oids asn1.RawValue `asn1:"tag:0,explicit,optional"`
41+
Oids asn1.RawValue
4242
}
4343
}
4444

0 commit comments

Comments
 (0)