-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdecrypt.go
100 lines (88 loc) · 2.85 KB
/
decrypt.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
package main
import (
"archive/zip"
"bytes"
"encoding/base64"
"errors"
"fmt"
"github.com/yoshi389111/git-caesar/caesar"
"github.com/yoshi389111/git-caesar/caesar/aes"
"github.com/yoshi389111/git-caesar/caesar/pubkeylib"
"github.com/yoshi389111/git-caesar/iolib"
)
func decrypt(peerPubKeys []caesar.PublicKey, prvKey caesar.PrivateKey, ciphertext []byte) ([]byte, error) {
// extract ZIP file
zipReader, err := zip.NewReader(bytes.NewReader(ciphertext), int64(len(ciphertext)))
if err != nil {
return nil, fmt.Errorf("Failed to expand zip file.\r\t%w", err)
}
caesarJsonBytes, err := iolib.ExtractZipEntry(zipReader, CAESAR_JSON)
if err != nil {
return nil, fmt.Errorf("Failed to extract `caesar.json`.\r\t%w", err)
}
caesarCipher, err := iolib.ExtractZipEntry(zipReader, CAESAR_CIPHER)
if err != nil {
return nil, fmt.Errorf("Failed to extract `caesar.cipher`.\r\t%w", err)
}
// unmarshal `caesar.json`
caesarJson, err := parseCaesarJson(caesarJsonBytes)
if err != nil {
return nil, fmt.Errorf("Failed to unmarshal `caesar.json`.\n\t%w", err)
}
// version validation
if caesarJson.Version != "1" {
return nil, fmt.Errorf("Unknown `caesar.json` version `%s`", caesarJson.Version)
}
// existence check of sender's public key
if peerPubKeys != nil {
verifySender := false
for _, peerPubKey := range peerPubKeys {
if peerPubKey.GetAuthKey() == caesarJson.Signer {
verifySender = true
break
}
}
if !verifySender {
return nil, errors.New("VERIFY_ERROR: not found sender publicKey.")
}
}
// verify signature
peerPubKey, err := pubkeylib.ParseAuthKey(caesarJson.Signer)
if err != nil {
return nil, fmt.Errorf("Invalid signer in `caesar.json`.\n\t%w", err)
}
sig, err := base64.StdEncoding.DecodeString(caesarJson.Signature)
if err != nil {
return nil, fmt.Errorf("Invalid signature in `caesar.json`.\n\t%w", err)
}
if !peerPubKey.Verify(caesarCipher, sig) {
return nil, errors.New("File is corrupted.")
}
// find the envelope corresponding to self private key
selfAuthKey, err := prvKey.GetAuthKey()
if err != nil {
return nil, fmt.Errorf("The authentication key could not be obtained from the private key during decryption.\n\t%w", err)
}
var targetEnvelope caesar.Envelope
for _, rawEnvelope := range caesarJson.Envelopes {
envelope := rawEnvelope.(caesar.Envelope)
if envelope.GetDest() == selfAuthKey {
targetEnvelope = envelope
break
}
}
if targetEnvelope == nil {
return nil, errors.New("Unable to decrypt with the specified private key.")
}
// key exchange
shareKey, err := prvKey.ExtractShareKey(targetEnvelope)
if err != nil {
return nil, fmt.Errorf("Key exchange failed.\n\t%w", err)
}
// decrypt `caesar.cipher`
plaintext, err := aes.Decrypt(shareKey, caesarCipher)
if err != nil {
return nil, fmt.Errorf("Failed to decrypt `caesar.cipher` with AES.\n\t%w", err)
}
return plaintext, nil
}