Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
8834bb0b
Commit
8834bb0b
authored
Jun 13, 2011
by
Adam Langley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
crypto/openpgp: flesh out Encrypt by adding support for signing.
R=bradfitz CC=golang-dev
https://golang.org/cl/4572059
parent
d164b608
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
158 additions
and
11 deletions
+158
-11
src/pkg/crypto/openpgp/keys.go
src/pkg/crypto/openpgp/keys.go
+1
-1
src/pkg/crypto/openpgp/packet/one_pass_signature.go
src/pkg/crypto/openpgp/packet/one_pass_signature.go
+26
-1
src/pkg/crypto/openpgp/write.go
src/pkg/crypto/openpgp/write.go
+97
-7
src/pkg/crypto/openpgp/write_test.go
src/pkg/crypto/openpgp/write_test.go
+34
-2
No files found.
src/pkg/crypto/openpgp/keys.go
View file @
8834bb0b
...
@@ -305,7 +305,7 @@ EachPacket:
...
@@ -305,7 +305,7 @@ EachPacket:
return
nil
,
error
.
StructuralError
(
"user ID packet not followed by self-signature"
)
return
nil
,
error
.
StructuralError
(
"user ID packet not followed by self-signature"
)
}
}
if
sig
.
SigType
==
packet
.
SigTypePositiveCert
&&
sig
.
IssuerKeyId
!=
nil
&&
*
sig
.
IssuerKeyId
==
e
.
PrimaryKey
.
KeyId
{
if
(
sig
.
SigType
==
packet
.
SigTypePositiveCert
||
sig
.
SigType
==
packet
.
SigTypeGenericCert
)
&&
sig
.
IssuerKeyId
!=
nil
&&
*
sig
.
IssuerKeyId
==
e
.
PrimaryKey
.
KeyId
{
if
err
=
e
.
PrimaryKey
.
VerifyUserIdSignature
(
pkt
.
Id
,
sig
);
err
!=
nil
{
if
err
=
e
.
PrimaryKey
.
VerifyUserIdSignature
(
pkt
.
Id
,
sig
);
err
!=
nil
{
return
nil
,
error
.
StructuralError
(
"user ID self-signature invalid: "
+
err
.
String
())
return
nil
,
error
.
StructuralError
(
"user ID self-signature invalid: "
+
err
.
String
())
}
}
...
...
src/pkg/crypto/openpgp/packet/one_pass_signature.go
View file @
8834bb0b
...
@@ -24,6 +24,8 @@ type OnePassSignature struct {
...
@@ -24,6 +24,8 @@ type OnePassSignature struct {
IsLast
bool
IsLast
bool
}
}
const
onePassSignatureVersion
=
3
func
(
ops
*
OnePassSignature
)
parse
(
r
io
.
Reader
)
(
err
os
.
Error
)
{
func
(
ops
*
OnePassSignature
)
parse
(
r
io
.
Reader
)
(
err
os
.
Error
)
{
var
buf
[
13
]
byte
var
buf
[
13
]
byte
...
@@ -31,7 +33,7 @@ func (ops *OnePassSignature) parse(r io.Reader) (err os.Error) {
...
@@ -31,7 +33,7 @@ func (ops *OnePassSignature) parse(r io.Reader) (err os.Error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
if
buf
[
0
]
!=
3
{
if
buf
[
0
]
!=
onePassSignatureVersion
{
err
=
error
.
UnsupportedError
(
"one-pass-signature packet version "
+
strconv
.
Itoa
(
int
(
buf
[
0
])))
err
=
error
.
UnsupportedError
(
"one-pass-signature packet version "
+
strconv
.
Itoa
(
int
(
buf
[
0
])))
}
}
...
@@ -47,3 +49,26 @@ func (ops *OnePassSignature) parse(r io.Reader) (err os.Error) {
...
@@ -47,3 +49,26 @@ func (ops *OnePassSignature) parse(r io.Reader) (err os.Error) {
ops
.
IsLast
=
buf
[
12
]
!=
0
ops
.
IsLast
=
buf
[
12
]
!=
0
return
return
}
}
// Serialize marshals the given OnePassSignature to w.
func
(
ops
*
OnePassSignature
)
Serialize
(
w
io
.
Writer
)
os
.
Error
{
var
buf
[
13
]
byte
buf
[
0
]
=
onePassSignatureVersion
buf
[
1
]
=
uint8
(
ops
.
SigType
)
var
ok
bool
buf
[
2
],
ok
=
s2k
.
HashToHashId
(
ops
.
Hash
)
if
!
ok
{
return
error
.
UnsupportedError
(
"hash type: "
+
strconv
.
Itoa
(
int
(
ops
.
Hash
)))
}
buf
[
3
]
=
uint8
(
ops
.
PubKeyAlgo
)
binary
.
BigEndian
.
PutUint64
(
buf
[
4
:
12
],
ops
.
KeyId
)
if
ops
.
IsLast
{
buf
[
12
]
=
1
}
if
err
:=
serializeHeader
(
w
,
packetTypeOnePassSignature
,
len
(
buf
));
err
!=
nil
{
return
err
}
_
,
err
:=
w
.
Write
(
buf
[
:
])
return
err
}
src/pkg/crypto/openpgp/write.go
View file @
8834bb0b
...
@@ -12,6 +12,7 @@ import (
...
@@ -12,6 +12,7 @@ import (
"crypto/openpgp/s2k"
"crypto/openpgp/s2k"
"crypto/rand"
"crypto/rand"
_
"crypto/sha256"
_
"crypto/sha256"
"hash"
"io"
"io"
"os"
"os"
"strconv"
"strconv"
...
@@ -144,11 +145,18 @@ func hashToHashId(h crypto.Hash) uint8 {
...
@@ -144,11 +145,18 @@ func hashToHashId(h crypto.Hash) uint8 {
}
}
// Encrypt encrypts a message to a number of recipients and, optionally, signs
// Encrypt encrypts a message to a number of recipients and, optionally, signs
// it. (Note: signing is not yet implemented.) hints contains optional
// it. hints contains optional information, that is also encrypted, that aids
// information, that is also encrypted, that aids the recipients in processing
// the recipients in processing the message. The resulting WriteCloser must
// the message. The resulting WriteCloser must be closed after the contents of
// be closed after the contents of the file have been written.
// the file have been written.
func
Encrypt
(
ciphertext
io
.
Writer
,
to
[]
*
Entity
,
signed
*
Entity
,
hints
*
FileHints
)
(
plaintext
io
.
WriteCloser
,
err
os
.
Error
)
{
func
Encrypt
(
ciphertext
io
.
Writer
,
to
[]
*
Entity
,
signed
*
Entity
,
hints
*
FileHints
)
(
plaintext
io
.
WriteCloser
,
err
os
.
Error
)
{
var
signer
*
packet
.
PrivateKey
if
signed
!=
nil
{
signer
=
signed
.
signingKey
()
.
PrivateKey
if
signer
==
nil
||
signer
.
Encrypted
{
return
nil
,
error
.
InvalidArgumentError
(
"signing key must be decrypted"
)
}
}
// These are the possible ciphers that we'll use for the message.
// These are the possible ciphers that we'll use for the message.
candidateCiphers
:=
[]
uint8
{
candidateCiphers
:=
[]
uint8
{
uint8
(
packet
.
CipherAES128
),
uint8
(
packet
.
CipherAES128
),
...
@@ -194,7 +202,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
...
@@ -194,7 +202,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
}
}
cipher
:=
packet
.
CipherFunction
(
candidateCiphers
[
0
])
cipher
:=
packet
.
CipherFunction
(
candidateCiphers
[
0
])
// hash
:= s2k.HashIdToHash(candidateHashes[0])
hash
,
_
:=
s2k
.
HashIdToHash
(
candidateHashes
[
0
])
symKey
:=
make
([]
byte
,
cipher
.
KeySize
())
symKey
:=
make
([]
byte
,
cipher
.
KeySize
())
if
_
,
err
:=
io
.
ReadFull
(
rand
.
Reader
,
symKey
);
err
!=
nil
{
if
_
,
err
:=
io
.
ReadFull
(
rand
.
Reader
,
symKey
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -206,13 +214,95 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
...
@@ -206,13 +214,95 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
}
}
}
}
w
,
err
:=
packet
.
SerializeSymmetricallyEncrypted
(
ciphertext
,
cipher
,
symKey
)
encryptedData
,
err
:=
packet
.
SerializeSymmetricallyEncrypted
(
ciphertext
,
cipher
,
symKey
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
if
signer
!=
nil
{
ops
:=
&
packet
.
OnePassSignature
{
SigType
:
packet
.
SigTypeBinary
,
Hash
:
hash
,
PubKeyAlgo
:
signer
.
PubKeyAlgo
,
KeyId
:
signer
.
KeyId
,
IsLast
:
true
,
}
if
err
:=
ops
.
Serialize
(
encryptedData
);
err
!=
nil
{
return
nil
,
err
}
}
if
hints
==
nil
{
if
hints
==
nil
{
hints
=
&
FileHints
{}
hints
=
&
FileHints
{}
}
}
return
packet
.
SerializeLiteral
(
w
,
hints
.
IsBinary
,
hints
.
FileName
,
hints
.
EpochSeconds
)
w
:=
encryptedData
if
signer
!=
nil
{
// If we need to write a signature packet after the literal
// data then we need to stop literalData from closing
// encryptedData.
w
=
noOpCloser
{
encryptedData
}
}
literalData
,
err
:=
packet
.
SerializeLiteral
(
w
,
hints
.
IsBinary
,
hints
.
FileName
,
hints
.
EpochSeconds
)
if
err
!=
nil
{
return
nil
,
err
}
if
signer
!=
nil
{
return
signatureWriter
{
encryptedData
,
literalData
,
hash
,
hash
.
New
(),
signer
},
nil
}
return
literalData
,
nil
}
// signatureWriter hashes the contents of a message while passing it along to
// literalData. When closed, it closes literalData, writes a signature packet
// to encryptedData and then also closes encryptedData.
type
signatureWriter
struct
{
encryptedData
io
.
WriteCloser
literalData
io
.
WriteCloser
hashType
crypto
.
Hash
h
hash
.
Hash
signer
*
packet
.
PrivateKey
}
func
(
s
signatureWriter
)
Write
(
data
[]
byte
)
(
int
,
os
.
Error
)
{
s
.
h
.
Write
(
data
)
return
s
.
literalData
.
Write
(
data
)
}
func
(
s
signatureWriter
)
Close
()
os
.
Error
{
sig
:=
&
packet
.
Signature
{
SigType
:
packet
.
SigTypeBinary
,
PubKeyAlgo
:
s
.
signer
.
PubKeyAlgo
,
Hash
:
s
.
hashType
,
CreationTime
:
uint32
(
time
.
Seconds
()),
IssuerKeyId
:
&
s
.
signer
.
KeyId
,
}
if
err
:=
sig
.
Sign
(
s
.
h
,
s
.
signer
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
literalData
.
Close
();
err
!=
nil
{
return
err
}
if
err
:=
sig
.
Serialize
(
s
.
encryptedData
);
err
!=
nil
{
return
err
}
return
s
.
encryptedData
.
Close
()
}
// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
// TODO: we have two of these in OpenPGP packages alone. This probably needs
// to be promoted somewhere more common.
type
noOpCloser
struct
{
w
io
.
Writer
}
func
(
c
noOpCloser
)
Write
(
data
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
return
c
.
w
.
Write
(
data
)
}
func
(
c
noOpCloser
)
Close
()
os
.
Error
{
return
nil
}
}
src/pkg/crypto/openpgp/write_test.go
View file @
8834bb0b
...
@@ -122,11 +122,16 @@ func TestSymmetricEncryption(t *testing.T) {
...
@@ -122,11 +122,16 @@ func TestSymmetricEncryption(t *testing.T) {
}
}
}
}
func
TestEncryption
(
t
*
testing
.
T
)
{
func
testEncryption
(
t
*
testing
.
T
,
isSigned
bool
)
{
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2PrivateHex
))
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2PrivateHex
))
var
signed
*
Entity
if
isSigned
{
signed
=
kring
[
0
]
}
buf
:=
new
(
bytes
.
Buffer
)
buf
:=
new
(
bytes
.
Buffer
)
w
,
err
:=
Encrypt
(
buf
,
kring
[
:
1
],
nil
,
/* not signed */
nil
/* no hints */
)
w
,
err
:=
Encrypt
(
buf
,
kring
[
:
1
],
signed
,
nil
/* no hints */
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"error in Encrypt: %s"
,
err
)
t
.
Errorf
(
"error in Encrypt: %s"
,
err
)
return
return
...
@@ -150,6 +155,16 @@ func TestEncryption(t *testing.T) {
...
@@ -150,6 +155,16 @@ func TestEncryption(t *testing.T) {
return
return
}
}
if
isSigned
{
expectedKeyId
:=
kring
[
0
]
.
signingKey
()
.
PublicKey
.
KeyId
if
md
.
SignedByKeyId
!=
expectedKeyId
{
t
.
Errorf
(
"message signed by wrong key id, got: %d, want: %d"
,
*
md
.
SignedBy
,
expectedKeyId
)
}
if
md
.
SignedBy
==
nil
{
t
.
Errorf
(
"failed to find the signing Entity"
)
}
}
plaintext
,
err
:=
ioutil
.
ReadAll
(
md
.
UnverifiedBody
)
plaintext
,
err
:=
ioutil
.
ReadAll
(
md
.
UnverifiedBody
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"error reading encrypted contents: %s"
,
err
)
t
.
Errorf
(
"error reading encrypted contents: %s"
,
err
)
...
@@ -164,4 +179,21 @@ func TestEncryption(t *testing.T) {
...
@@ -164,4 +179,21 @@ func TestEncryption(t *testing.T) {
if
string
(
plaintext
)
!=
message
{
if
string
(
plaintext
)
!=
message
{
t
.
Errorf
(
"got: %s, want: %s"
,
string
(
plaintext
),
message
)
t
.
Errorf
(
"got: %s, want: %s"
,
string
(
plaintext
),
message
)
}
}
if
isSigned
{
if
md
.
SignatureError
!=
nil
{
t
.
Errorf
(
"signature error: %s"
,
err
)
}
if
md
.
Signature
==
nil
{
t
.
Error
(
"signature missing"
)
}
}
}
func
TestEncryption
(
t
*
testing
.
T
)
{
testEncryption
(
t
,
false
/* not signed */
)
}
func
TestEncryptAndSign
(
t
*
testing
.
T
)
{
testEncryption
(
t
,
true
/* signed */
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment