@@ -3,6 +3,7 @@ package main
33import (
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+
6692func 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}
0 commit comments