Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
6ca009f5
Commit
6ca009f5
authored
Feb 25, 2011
by
Adam Langley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
crypto/openpgp: add package
R=bradfitzgo CC=golang-dev
https://golang.org/cl/3989052
parent
27ccb41c
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1187 additions
and
3 deletions
+1187
-3
Makefile
src/pkg/Makefile
+6
-0
Makefile
src/pkg/crypto/openpgp/Makefile
+14
-0
canonical_text.go
src/pkg/crypto/openpgp/canonical_text.go
+58
-0
canonical_text_test.go
src/pkg/crypto/openpgp/canonical_text_test.go
+50
-0
keys.go
src/pkg/crypto/openpgp/keys.go
+280
-0
packet.go
src/pkg/crypto/openpgp/packet/packet.go
+2
-2
public_key.go
src/pkg/crypto/openpgp/packet/public_key.go
+1
-1
read.go
src/pkg/crypto/openpgp/read.go
+413
-0
read_test.go
src/pkg/crypto/openpgp/read_test.go
+237
-0
write.go
src/pkg/crypto/openpgp/write.go
+92
-0
write_test.go
src/pkg/crypto/openpgp/write_test.go
+34
-0
No files found.
src/pkg/Makefile
View file @
6ca009f5
...
...
@@ -42,6 +42,11 @@ DIRS=\
crypto/md4
\
crypto/md5
\
crypto/ocsp
\
crypto/openpgp
\
crypto/openpgp/armor
\
crypto/openpgp/error
\
crypto/openpgp/packet
\
crypto/openpgp/s2k
\
crypto/rand
\
crypto/rc4
\
crypto/ripemd160
\
...
...
@@ -158,6 +163,7 @@ endif
NOTEST
=
\
crypto
\
crypto/openpgp/error
\
debug/proc
\
exp/draw/x11
\
go/ast
\
...
...
src/pkg/crypto/openpgp/Makefile
0 → 100644
View file @
6ca009f5
# Copyright 2011 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include
../../../Make.inc
TARG
=
crypto/openpgp
GOFILES
=
\
canonical_text.go
\
keys.go
\
read.go
\
write.go
\
include
../../../Make.pkg
src/pkg/crypto/openpgp/canonical_text.go
0 → 100644
View file @
6ca009f5
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
openpgp
import
(
"hash"
"os"
)
// NewCanonicalTextHash reformats text written to it into the canonical
// form and then applies the hash h. See RFC 4880, section 5.2.1.
func
NewCanonicalTextHash
(
h
hash
.
Hash
)
hash
.
Hash
{
return
&
canonicalTextHash
{
h
,
0
}
}
type
canonicalTextHash
struct
{
h
hash
.
Hash
s
int
}
var
newline
=
[]
byte
{
'\r'
,
'\n'
}
func
(
cth
*
canonicalTextHash
)
Write
(
buf
[]
byte
)
(
int
,
os
.
Error
)
{
start
:=
0
for
i
,
c
:=
range
buf
{
switch
cth
.
s
{
case
0
:
if
c
==
'\r'
{
cth
.
s
=
1
}
else
if
c
==
'\n'
{
cth
.
h
.
Write
(
buf
[
start
:
i
])
cth
.
h
.
Write
(
newline
)
start
=
i
+
1
}
case
1
:
cth
.
s
=
0
}
}
cth
.
h
.
Write
(
buf
[
start
:
])
return
len
(
buf
),
nil
}
func
(
cth
*
canonicalTextHash
)
Sum
()
[]
byte
{
return
cth
.
h
.
Sum
()
}
func
(
cth
*
canonicalTextHash
)
Reset
()
{
cth
.
h
.
Reset
()
cth
.
s
=
0
}
func
(
cth
*
canonicalTextHash
)
Size
()
int
{
return
cth
.
h
.
Size
()
}
src/pkg/crypto/openpgp/canonical_text_test.go
0 → 100644
View file @
6ca009f5
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
openpgp
import
(
"bytes"
"os"
"testing"
)
type
recordingHash
struct
{
buf
*
bytes
.
Buffer
}
func
(
r
recordingHash
)
Write
(
b
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
return
r
.
buf
.
Write
(
b
)
}
func
(
r
recordingHash
)
Sum
()
[]
byte
{
return
r
.
buf
.
Bytes
()
}
func
(
r
recordingHash
)
Reset
()
{
panic
(
"shouldn't be called"
)
}
func
(
r
recordingHash
)
Size
()
int
{
panic
(
"shouldn't be called"
)
}
func
testCanonicalText
(
t
*
testing
.
T
,
input
,
expected
string
)
{
r
:=
recordingHash
{
bytes
.
NewBuffer
(
nil
)}
c
:=
NewCanonicalTextHash
(
r
)
c
.
Write
([]
byte
(
input
))
result
:=
c
.
Sum
()
if
expected
!=
string
(
result
)
{
t
.
Errorf
(
"input: %x got: %x want: %x"
,
input
,
result
,
expected
)
}
}
func
TestCanonicalText
(
t
*
testing
.
T
)
{
testCanonicalText
(
t
,
"foo
\n
"
,
"foo
\r\n
"
)
testCanonicalText
(
t
,
"foo"
,
"foo"
)
testCanonicalText
(
t
,
"foo
\r\n
"
,
"foo
\r\n
"
)
testCanonicalText
(
t
,
"foo
\r\n
bar"
,
"foo
\r\n
bar"
)
testCanonicalText
(
t
,
"foo
\r\n
bar
\n\n
"
,
"foo
\r\n
bar
\r\n\r\n
"
)
}
src/pkg/crypto/openpgp/keys.go
0 → 100644
View file @
6ca009f5
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
openpgp
import
(
"crypto/openpgp/error"
"crypto/openpgp/packet"
"io"
"os"
)
// PublicKeyType is the armor type for a PGP public key.
var
PublicKeyType
=
"PGP PUBLIC KEY BLOCK"
// An Entity represents the components of an OpenPGP key: a primary public key
// (which must be a signing key), one or more identities claimed by that key,
// and zero or more subkeys, which may be encryption keys.
type
Entity
struct
{
PrimaryKey
*
packet
.
PublicKey
PrivateKey
*
packet
.
PrivateKey
Identities
map
[
string
]
*
Identity
// indexed by Identity.Name
Subkeys
[]
Subkey
}
// An Identity represents an identity claimed by an Entity and zero or more
// assertions by other entities about that claim.
type
Identity
struct
{
Name
string
// by convention, has the form "Full Name (comment) <email@example.com>"
UserId
*
packet
.
UserId
SelfSignature
*
packet
.
Signature
Signatures
[]
*
packet
.
Signature
}
// A Subkey is an additional public key in an Entity. Subkeys can be used for
// encryption.
type
Subkey
struct
{
PublicKey
*
packet
.
PublicKey
PrivateKey
*
packet
.
PrivateKey
Sig
*
packet
.
Signature
}
// A Key identifies a specific public key in an Entity. This is either the
// Entity's primary key or a subkey.
type
Key
struct
{
Entity
*
Entity
PublicKey
*
packet
.
PublicKey
PrivateKey
*
packet
.
PrivateKey
SelfSignature
*
packet
.
Signature
}
// A KeyRing provides access to public and private keys.
type
KeyRing
interface
{
// KeysById returns the set of keys that have the given key id.
KeysById
(
id
uint64
)
[]
Key
// DecryptionKeys returns all private keys that are valid for
// decryption.
DecryptionKeys
()
[]
Key
}
// An EntityList contains one or more Entities.
type
EntityList
[]
*
Entity
// KeysById returns the set of keys that have the given key id.
func
(
el
EntityList
)
KeysById
(
id
uint64
)
(
keys
[]
Key
)
{
for
_
,
e
:=
range
el
{
if
e
.
PrimaryKey
.
KeyId
==
id
{
var
selfSig
*
packet
.
Signature
for
_
,
ident
:=
range
e
.
Identities
{
if
selfSig
==
nil
{
selfSig
=
ident
.
SelfSignature
}
else
if
ident
.
SelfSignature
.
IsPrimaryId
!=
nil
&&
*
ident
.
SelfSignature
.
IsPrimaryId
{
selfSig
=
ident
.
SelfSignature
break
}
}
keys
=
append
(
keys
,
Key
{
e
,
e
.
PrimaryKey
,
e
.
PrivateKey
,
selfSig
})
}
for
_
,
subKey
:=
range
e
.
Subkeys
{
if
subKey
.
PublicKey
.
KeyId
==
id
{
keys
=
append
(
keys
,
Key
{
e
,
subKey
.
PublicKey
,
subKey
.
PrivateKey
,
subKey
.
Sig
})
}
}
}
return
}
// DecryptionKeys returns all private keys that are valid for decryption.
func
(
el
EntityList
)
DecryptionKeys
()
(
keys
[]
Key
)
{
for
_
,
e
:=
range
el
{
for
_
,
subKey
:=
range
e
.
Subkeys
{
if
subKey
.
PrivateKey
!=
nil
&&
(
!
subKey
.
Sig
.
FlagsValid
||
subKey
.
Sig
.
FlagEncryptStorage
||
subKey
.
Sig
.
FlagEncryptCommunications
)
{
keys
=
append
(
keys
,
Key
{
e
,
subKey
.
PublicKey
,
subKey
.
PrivateKey
,
subKey
.
Sig
})
}
}
}
return
}
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
func
ReadArmoredKeyRing
(
r
io
.
Reader
)
(
EntityList
,
os
.
Error
)
{
body
,
err
:=
readArmored
(
r
,
PublicKeyType
)
if
err
!=
nil
{
return
nil
,
err
}
return
ReadKeyRing
(
body
)
}
// ReadKeyRing reads one or more public/private keys, ignoring unsupported keys.
func
ReadKeyRing
(
r
io
.
Reader
)
(
el
EntityList
,
err
os
.
Error
)
{
packets
:=
packet
.
NewReader
(
r
)
for
{
var
e
*
Entity
e
,
err
=
readEntity
(
packets
)
if
err
!=
nil
{
if
_
,
ok
:=
err
.
(
error
.
UnsupportedError
);
ok
{
err
=
readToNextPublicKey
(
packets
)
}
if
err
==
os
.
EOF
{
err
=
nil
return
}
if
err
!=
nil
{
el
=
nil
return
}
}
else
{
el
=
append
(
el
,
e
)
}
}
return
}
// readToNextPublicKey reads packets until the start of the entity and leaves
// the first packet of the new entity in the Reader.
func
readToNextPublicKey
(
packets
*
packet
.
Reader
)
(
err
os
.
Error
)
{
var
p
packet
.
Packet
for
{
p
,
err
=
packets
.
Next
()
if
err
==
os
.
EOF
{
return
}
else
if
err
!=
nil
{
if
_
,
ok
:=
err
.
(
error
.
UnsupportedError
);
ok
{
err
=
nil
continue
}
return
}
if
pk
,
ok
:=
p
.
(
*
packet
.
PublicKey
);
ok
&&
!
pk
.
IsSubkey
{
packets
.
Unread
(
p
)
return
}
}
panic
(
"unreachable"
)
}
// readEntity reads an entity (public key, identities, subkeys etc) from the
// given Reader.
func
readEntity
(
packets
*
packet
.
Reader
)
(
*
Entity
,
os
.
Error
)
{
e
:=
new
(
Entity
)
e
.
Identities
=
make
(
map
[
string
]
*
Identity
)
p
,
err
:=
packets
.
Next
()
if
err
!=
nil
{
return
nil
,
err
}
var
ok
bool
if
e
.
PrimaryKey
,
ok
=
p
.
(
*
packet
.
PublicKey
);
!
ok
{
if
e
.
PrivateKey
,
ok
=
p
.
(
*
packet
.
PrivateKey
);
!
ok
{
packets
.
Unread
(
p
)
return
nil
,
error
.
StructuralError
(
"first packet was not a public/private key"
)
}
else
{
e
.
PrimaryKey
=
&
e
.
PrivateKey
.
PublicKey
}
}
var
current
*
Identity
EachPacket
:
for
{
p
,
err
:=
packets
.
Next
()
if
err
==
os
.
EOF
{
break
}
else
if
err
!=
nil
{
return
nil
,
err
}
switch
pkt
:=
p
.
(
type
)
{
case
*
packet
.
UserId
:
current
=
new
(
Identity
)
current
.
Name
=
pkt
.
Id
current
.
UserId
=
pkt
e
.
Identities
[
pkt
.
Id
]
=
current
p
,
err
=
packets
.
Next
()
if
err
==
os
.
EOF
{
err
=
io
.
ErrUnexpectedEOF
}
if
err
!=
nil
{
if
_
,
ok
:=
err
.
(
error
.
UnsupportedError
);
ok
{
return
nil
,
err
}
return
nil
,
error
.
StructuralError
(
"identity self-signature invalid: "
+
err
.
String
())
}
current
.
SelfSignature
,
ok
=
p
.
(
*
packet
.
Signature
)
if
!
ok
{
return
nil
,
error
.
StructuralError
(
"user ID packet not followed by self signature"
)
}
if
current
.
SelfSignature
.
SigType
!=
packet
.
SigTypePositiveCert
{
return
nil
,
error
.
StructuralError
(
"user ID self-signature with wrong type"
)
}
if
err
=
e
.
PrimaryKey
.
VerifyUserIdSignature
(
pkt
.
Id
,
current
.
SelfSignature
);
err
!=
nil
{
return
nil
,
error
.
StructuralError
(
"user ID self-signature invalid: "
+
err
.
String
())
}
case
*
packet
.
Signature
:
if
current
==
nil
{
return
nil
,
error
.
StructuralError
(
"signature packet found before user id packet"
)
}
current
.
Signatures
=
append
(
current
.
Signatures
,
pkt
)
case
*
packet
.
PrivateKey
:
if
pkt
.
IsSubkey
==
false
{
packets
.
Unread
(
p
)
break
EachPacket
}
err
=
addSubkey
(
e
,
packets
,
&
pkt
.
PublicKey
,
pkt
)
if
err
!=
nil
{
return
nil
,
err
}
case
*
packet
.
PublicKey
:
if
pkt
.
IsSubkey
==
false
{
packets
.
Unread
(
p
)
break
EachPacket
}
err
=
addSubkey
(
e
,
packets
,
pkt
,
nil
)
if
err
!=
nil
{
return
nil
,
err
}
default
:
// we ignore unknown packets
}
}
if
len
(
e
.
Identities
)
==
0
{
return
nil
,
error
.
StructuralError
(
"entity without any identities"
)
}
return
e
,
nil
}
func
addSubkey
(
e
*
Entity
,
packets
*
packet
.
Reader
,
pub
*
packet
.
PublicKey
,
priv
*
packet
.
PrivateKey
)
os
.
Error
{
var
subKey
Subkey
subKey
.
PublicKey
=
pub
subKey
.
PrivateKey
=
priv
p
,
err
:=
packets
.
Next
()
if
err
==
os
.
EOF
{
return
io
.
ErrUnexpectedEOF
}
if
err
!=
nil
{
return
error
.
StructuralError
(
"subkey signature invalid: "
+
err
.
String
())
}
var
ok
bool
subKey
.
Sig
,
ok
=
p
.
(
*
packet
.
Signature
)
if
!
ok
{
return
error
.
StructuralError
(
"subkey packet not followed by signature"
)
}
if
subKey
.
Sig
.
SigType
!=
packet
.
SigTypeSubkeyBinding
{
return
error
.
StructuralError
(
"subkey signature with wrong type"
)
}
err
=
e
.
PrimaryKey
.
VerifyKeySignature
(
subKey
.
PublicKey
,
subKey
.
Sig
)
if
err
!=
nil
{
return
error
.
StructuralError
(
"subkey signature invalid: "
+
err
.
String
())
}
e
.
Subkeys
=
append
(
e
.
Subkeys
,
subKey
)
return
nil
}
src/pkg/crypto/openpgp/packet/packet.go
View file @
6ca009f5
...
...
@@ -261,13 +261,13 @@ func Read(r io.Reader) (p Packet, err os.Error) {
case
packetTypePrivateKey
,
packetTypePrivateSubkey
:
pk
:=
new
(
PrivateKey
)
if
tag
==
packetTypePrivateSubkey
{
pk
.
IsSub
K
ey
=
true
pk
.
IsSub
k
ey
=
true
}
p
=
pk
case
packetTypePublicKey
,
packetTypePublicSubkey
:
pk
:=
new
(
PublicKey
)
if
tag
==
packetTypePublicSubkey
{
pk
.
IsSub
K
ey
=
true
pk
.
IsSub
k
ey
=
true
}
p
=
pk
case
packetTypeCompressed
:
...
...
src/pkg/crypto/openpgp/packet/public_key.go
View file @
6ca009f5
...
...
@@ -23,7 +23,7 @@ type PublicKey struct {
PublicKey
interface
{}
// Either a *rsa.PublicKey or *dsa.PublicKey
Fingerprint
[
20
]
byte
KeyId
uint64
IsSub
K
ey
bool
IsSub
k
ey
bool
n
,
e
,
p
,
q
,
g
,
y
parsedMPI
}
...
...
src/pkg/crypto/openpgp/read.go
0 → 100644
View file @
6ca009f5
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This openpgp package implements high level operations on OpenPGP messages.
package
openpgp
import
(
"crypto"
"crypto/openpgp/armor"
"crypto/openpgp/error"
"crypto/openpgp/packet"
"crypto/rsa"
_
"crypto/sha256"
"hash"
"io"
"os"
"strconv"
)
// SignatureType is the armor type for a PGP signature.
var
SignatureType
=
"PGP SIGNATURE"
// readArmored reads an armored block with the given type.
func
readArmored
(
r
io
.
Reader
,
expectedType
string
)
(
body
io
.
Reader
,
err
os
.
Error
)
{
block
,
err
:=
armor
.
Decode
(
r
)
if
err
!=
nil
{
return
}
if
block
.
Type
!=
expectedType
{
return
nil
,
error
.
InvalidArgumentError
(
"expected '"
+
expectedType
+
"', got: "
+
block
.
Type
)
}
return
block
.
Body
,
nil
}
// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
// signed message.
type
MessageDetails
struct
{
IsEncrypted
bool
// true if the message was encrypted.
EncryptedToKeyIds
[]
uint64
// the list of recipient key ids.
IsSymmetricallyEncrypted
bool
// true if a passphrase could have decrypted the message.
DecryptedWith
Key
// the private key used to decrypt the message, if any.
IsSigned
bool
// true if the message is signed.
SignedByKeyId
uint64
// the key id of the signer, if any.
SignedBy
*
Key
// the key of the signer, if availible.
LiteralData
*
packet
.
LiteralData
// the metadata of the contents
UnverifiedBody
io
.
Reader
// the contents of the message.
// If IsSigned is true and SignedBy is non-zero then the signature will
// be verified as UnverifiedBody is read. The signature cannot be
// checked until the whole of UnverifiedBody is read so UnverifiedBody
// must be consumed until EOF before the data can trusted. Even if a
// message isn't signed (or the signer is unknown) the data may contain
// an authentication code that is only checked once UnverifiedBody has
// been consumed. Once EOF has been seen, the following fields are
// valid. (An authentication code failure is reported as a
// SignatureError error when reading from UnverifiedBody.)
SignatureError
os
.
Error
// nil if the signature is good.
Signature
*
packet
.
Signature
// the signature packet itself.
decrypted
io
.
ReadCloser
}
// A PromptFunction is used as a callback by functions that may need to decrypt
// a private key, or prompt for a passphrase. It is called with a list of
// acceptable, encrypted private keys and a boolean that indicates whether a
// passphrase is usable. It should either decrypt a private key or return a
// passphrase to try. If the decrypted private key or given passphrase isn't
// correct, the function will be called again, forever. Any error returned will
// be passed up.
type
PromptFunction
func
(
keys
[]
Key
,
symmetric
bool
)
([]
byte
,
os
.
Error
)
// A keyEnvelopePair is used to store a private key with the envelope that
// contains a symmetric key, encrypted with that key.
type
keyEnvelopePair
struct
{
key
Key
encryptedKey
*
packet
.
EncryptedKey
}
// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
// The given KeyRing should contain both public keys (for signature
// verification) and, possibly encrypted, private keys for decrypting.
func
ReadMessage
(
r
io
.
Reader
,
keyring
KeyRing
,
prompt
PromptFunction
)
(
md
*
MessageDetails
,
err
os
.
Error
)
{
var
p
packet
.
Packet
var
symKeys
[]
*
packet
.
SymmetricKeyEncrypted
var
pubKeys
[]
keyEnvelopePair
var
se
*
packet
.
SymmetricallyEncrypted
packets
:=
packet
.
NewReader
(
r
)
md
=
new
(
MessageDetails
)
md
.
IsEncrypted
=
true
// The message, if encrypted, starts with a number of packets
// containing an encrypted decryption key. The decryption key is either
// encrypted to a public key, or with a passphrase. This loop
// collects these packets.
ParsePackets
:
for
{
p
,
err
=
packets
.
Next
()
if
err
!=
nil
{
return
nil
,
err
}
switch
p
:=
p
.
(
type
)
{
case
*
packet
.
SymmetricKeyEncrypted
:
// This packet contains the decryption key encrypted with a passphrase.
md
.
IsSymmetricallyEncrypted
=
true
symKeys
=
append
(
symKeys
,
p
)
case
*
packet
.
EncryptedKey
:
// This packet contains the decryption key encrypted to a public key.
md
.
EncryptedToKeyIds
=
append
(
md
.
EncryptedToKeyIds
,
p
.
KeyId
)
if
p
.
Algo
!=
packet
.
PubKeyAlgoRSA
&&
p
.
Algo
!=
packet
.
PubKeyAlgoRSAEncryptOnly
{
continue
}
var
keys
[]
Key
if
p
.
KeyId
==
0
{
keys
=
keyring
.
DecryptionKeys
()
}
else
{
keys
=
keyring
.
KeysById
(
p
.
KeyId
)
}
for
_
,
k
:=
range
keys
{
pubKeys
=
append
(
pubKeys
,
keyEnvelopePair
{
k
,
p
})
}
case
*
packet
.
SymmetricallyEncrypted
:
se
=
p
break
ParsePackets
case
*
packet
.
Compressed
,
*
packet
.
LiteralData
,
*
packet
.
OnePassSignature
:
// This message isn't encrypted.
if
len
(
symKeys
)
!=
0
||
len
(
pubKeys
)
!=
0
{
return
nil
,
error
.
StructuralError
(
"key material not followed by encrypted message"
)
}
packets
.
Unread
(
p
)
return
readSignedMessage
(
packets
,
nil
,
keyring
)
}
}
var
candidates
[]
Key
var
decrypted
io
.
ReadCloser
// Now that we have the list of encrypted keys we need to decrypt at
// least one of them or, if we cannot, we need to call the prompt
// function so that it can decrypt a key or give us a passphrase.
FindKey
:
for
{
// See if any of the keys already have a private key availible
candidates
=
candidates
[
:
0
]
candidateFingerprints
:=
make
(
map
[
string
]
bool
)
for
_
,
pk
:=
range
pubKeys
{
if
pk
.
key
.
PrivateKey
==
nil
{
continue
}
if
!
pk
.
key
.
PrivateKey
.
Encrypted
{
if
len
(
pk
.
encryptedKey
.
Key
)
==
0
{
pk
.
encryptedKey
.
DecryptRSA
(
pk
.
key
.
PrivateKey
.
PrivateKey
.
(
*
rsa
.
PrivateKey
))
}
if
len
(
pk
.
encryptedKey
.
Key
)
==
0
{
continue
}
decrypted
,
err
=
se
.
Decrypt
(
pk
.
encryptedKey
.
CipherFunc
,
pk
.
encryptedKey
.
Key
)
if
err
!=
nil
&&
err
!=
error
.
KeyIncorrectError
{
return
nil
,
err
}
if
decrypted
!=
nil
{
md
.
DecryptedWith
=
pk
.
key
break
FindKey
}
}
else
{
fpr
:=
string
(
pk
.
key
.
PublicKey
.
Fingerprint
[
:
])
if
v
:=
candidateFingerprints
[
fpr
];
v
{
continue
}
candidates
=
append
(
candidates
,
pk
.
key
)
candidateFingerprints
[
fpr
]
=
true
}
}
if
len
(
candidates
)
==
0
&&
len
(
symKeys
)
==
0
{
return
nil
,
error
.
KeyIncorrectError
}
if
prompt
==
nil
{
return
nil
,
error
.
KeyIncorrectError
}
passphrase
,
err
:=
prompt
(
candidates
,
len
(
symKeys
)
!=
0
)
if
err
!=
nil
{
return
nil
,
err
}
// Try the symmetric passphrase first
if
len
(
symKeys
)
!=
0
&&
passphrase
!=
nil
{
for
_
,
s
:=
range
symKeys
{
err
=
s
.
Decrypt
(
passphrase
)
if
err
==
nil
&&
!
s
.
Encrypted
{
decrypted
,
err
=
se
.
Decrypt
(
s
.
CipherFunc
,
s
.
Key
)
if
err
!=
nil
&&
err
!=
error
.
KeyIncorrectError
{
return
nil
,
err
}
if
decrypted
!=
nil
{
break
FindKey
}
}
}
}
}
md
.
decrypted
=
decrypted
packets
.
Push
(
decrypted
)
return
readSignedMessage
(
packets
,
md
,
keyring
)
}
// readSignedMessage reads a possibily signed message if mdin is non-zero then
// that structure is updated and returned. Otherwise a fresh MessageDetails is
// used.
func
readSignedMessage
(
packets
*
packet
.
Reader
,
mdin
*
MessageDetails
,
keyring
KeyRing
)
(
md
*
MessageDetails
,
err
os
.
Error
)
{
if
mdin
==
nil
{
mdin
=
new
(
MessageDetails
)
}
md
=
mdin
var
p
packet
.
Packet
var
h
hash
.
Hash
var
wrappedHash
hash
.
Hash
FindLiteralData
:
for
{
p
,
err
=
packets
.
Next
()
if
err
!=
nil
{
return
nil
,
err
}
switch
p
:=
p
.
(
type
)
{
case
*
packet
.
Compressed
:
packets
.
Push
(
p
.
Body
)
case
*
packet
.
OnePassSignature
:
if
!
p
.
IsLast
{
return
nil
,
error
.
UnsupportedError
(
"nested signatures"
)
}
h
,
wrappedHash
,
err
=
hashForSignature
(
p
.
Hash
,
p
.
SigType
)
if
err
!=
nil
{
md
=
nil
return
}
md
.
IsSigned
=
true
md
.
SignedByKeyId
=
p
.
KeyId
keys
:=
keyring
.
KeysById
(
p
.
KeyId
)
for
_
,
key
:=
range
keys
{
if
key
.
SelfSignature
.
FlagsValid
&&
!
key
.
SelfSignature
.
FlagSign
{
continue
}
md
.
SignedBy
=
&
key
}
case
*
packet
.
LiteralData
:
md
.
LiteralData
=
p
break
FindLiteralData
}
}
if
md
.
SignedBy
!=
nil
{
md
.
UnverifiedBody
=
&
signatureCheckReader
{
packets
,
h
,
wrappedHash
,
md
}
}
else
if
md
.
decrypted
!=
nil
{
md
.
UnverifiedBody
=
checkReader
{
md
}
}
else
{
md
.
UnverifiedBody
=
md
.
LiteralData
.
Body
}
return
md
,
nil
}
// hashForSignature returns a pair of hashes that can be used to verify a
// signature. The signature may specify that the contents of the signed message
// should be preprocessed (i.e. to normalise line endings). Thus this function
// returns two hashes. The second should be used to hash the message itself and
// performs any needed preprocessing.
func
hashForSignature
(
hashId
crypto
.
Hash
,
sigType
packet
.
SignatureType
)
(
hash
.
Hash
,
hash
.
Hash
,
os
.
Error
)
{
h
:=
hashId
.
New
()
if
h
==
nil
{
return
nil
,
nil
,
error
.
UnsupportedError
(
"hash not availible: "
+
strconv
.
Itoa
(
int
(
hashId
)))
}
switch
sigType
{
case
packet
.
SigTypeBinary
:
return
h
,
h
,
nil
case
packet
.
SigTypeText
:
return
h
,
NewCanonicalTextHash
(
h
),
nil
}
return
nil
,
nil
,
error
.
UnsupportedError
(
"unsupported signature type: "
+
strconv
.
Itoa
(
int
(
sigType
)))
}
// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
// MDC checks.
type
checkReader
struct
{
md
*
MessageDetails
}
func
(
cr
checkReader
)
Read
(
buf
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
n
,
err
=
cr
.
md
.
LiteralData
.
Body
.
Read
(
buf
)
if
err
==
os
.
EOF
{
mdcErr
:=
cr
.
md
.
decrypted
.
Close
()
if
mdcErr
!=
nil
{
err
=
mdcErr
}
}
return
}
// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
// the data as it is read. When it sees an EOF from the underlying io.Reader
// it parses and checks a trailing Signature packet and triggers any MDC checks.
type
signatureCheckReader
struct
{
packets
*
packet
.
Reader
h
,
wrappedHash
hash
.
Hash
md
*
MessageDetails
}
func
(
scr
*
signatureCheckReader
)
Read
(
buf
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
n
,
err
=
scr
.
md
.
LiteralData
.
Body
.
Read
(
buf
)
scr
.
wrappedHash
.
Write
(
buf
[
:
n
])
if
err
==
os
.
EOF
{
var
p
packet
.
Packet
p
,
scr
.
md
.
SignatureError
=
scr
.
packets
.
Next
()
if
scr
.
md
.
SignatureError
!=
nil
{
return
}
var
ok
bool
if
scr
.
md
.
Signature
,
ok
=
p
.
(
*
packet
.
Signature
);
!
ok
{
scr
.
md
.
SignatureError
=
error
.
StructuralError
(
"LiteralData not followed by Signature"
)
return
}
scr
.
md
.
SignatureError
=
scr
.
md
.
SignedBy
.
PublicKey
.
VerifySignature
(
scr
.
h
,
scr
.
md
.
Signature
)
// The SymmetricallyEncrypted packet, if any, might have an
// unsigned hash of its own. In order to check this we need to
// close that Reader.
if
scr
.
md
.
decrypted
!=
nil
{
mdcErr
:=
scr
.
md
.
decrypted
.
Close
()
if
mdcErr
!=
nil
{
err
=
mdcErr
}
}
}
return
}
// CheckDetachedSignature takes a signed file and a detached signature and
// returns the signer if the signature is valid. If the signer isn't know,
// UnknownIssuerError is returned.
func
CheckDetachedSignature
(
keyring
KeyRing
,
signed
,
signature
io
.
Reader
)
(
signer
*
Entity
,
err
os
.
Error
)
{
p
,
err
:=
packet
.
Read
(
signature
)
if
err
!=
nil
{
return
}
sig
,
ok
:=
p
.
(
*
packet
.
Signature
)
if
!
ok
{
return
nil
,
error
.
StructuralError
(
"non signature packet found"
)
}
if
sig
.
IssuerKeyId
==
nil
{
return
nil
,
error
.
StructuralError
(
"signature doesn't have an issuer"
)
}
keys
:=
keyring
.
KeysById
(
*
sig
.
IssuerKeyId
)
if
len
(
keys
)
==
0
{
return
nil
,
error
.
UnknownIssuerError
}
h
,
wrappedHash
,
err
:=
hashForSignature
(
sig
.
Hash
,
sig
.
SigType
)
if
err
!=
nil
{
return
}
_
,
err
=
io
.
Copy
(
wrappedHash
,
signed
)
if
err
!=
nil
&&
err
!=
os
.
EOF
{
return
}
for
_
,
key
:=
range
keys
{
if
key
.
SelfSignature
.
FlagsValid
&&
!
key
.
SelfSignature
.
FlagSign
{
continue
}
err
=
key
.
PublicKey
.
VerifySignature
(
h
,
sig
)
if
err
==
nil
{
return
key
.
Entity
,
nil
}
}
if
err
!=
nil
{
return
}
return
nil
,
error
.
UnknownIssuerError
}
// CheckArmoredDetachedSignature performs the same actions as
// CheckDetachedSignature but expects the signature to be armored.
func
CheckArmoredDetachedSignature
(
keyring
KeyRing
,
signed
,
signature
io
.
Reader
)
(
signer
*
Entity
,
err
os
.
Error
)
{
body
,
err
:=
readArmored
(
signature
,
SignatureType
)
if
err
!=
nil
{
return
}
return
CheckDetachedSignature
(
keyring
,
signed
,
body
)
}
src/pkg/crypto/openpgp/read_test.go
0 → 100644
View file @
6ca009f5
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
openpgp
import
(
"bytes"
"crypto/openpgp/error"
"encoding/hex"
"io"
"io/ioutil"
"os"
"testing"
)
func
readerFromHex
(
s
string
)
io
.
Reader
{
data
,
err
:=
hex
.
DecodeString
(
s
)
if
err
!=
nil
{
panic
(
"readerFromHex: bad input"
)
}
return
bytes
.
NewBuffer
(
data
)
}
func
TestReadKeyRing
(
t
*
testing
.
T
)
{
kring
,
err
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2Hex
))
if
err
!=
nil
{
t
.
Error
(
err
)
return
}
if
len
(
kring
)
!=
2
||
uint32
(
kring
[
0
]
.
PrimaryKey
.
KeyId
)
!=
0xC20C31BB
||
uint32
(
kring
[
1
]
.
PrimaryKey
.
KeyId
)
!=
0x1E35246B
{
t
.
Errorf
(
"bad keyring: %#v"
,
kring
)
}
}
func
TestReadPrivateKeyRing
(
t
*
testing
.
T
)
{
kring
,
err
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2PrivateHex
))
if
err
!=
nil
{
t
.
Error
(
err
)
return
}
if
len
(
kring
)
!=
2
||
uint32
(
kring
[
0
]
.
PrimaryKey
.
KeyId
)
!=
0xC20C31BB
||
uint32
(
kring
[
1
]
.
PrimaryKey
.
KeyId
)
!=
0x1E35246B
||
kring
[
0
]
.
PrimaryKey
==
nil
{
t
.
Errorf
(
"bad keyring: %#v"
,
kring
)
}
}
func
TestGetKeyById
(
t
*
testing
.
T
)
{
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2Hex
))
keys
:=
kring
.
KeysById
(
0xa34d7e18c20c31bb
)
if
len
(
keys
)
!=
1
||
keys
[
0
]
.
Entity
!=
kring
[
0
]
{
t
.
Errorf
(
"bad result for 0xa34d7e18c20c31bb: %#v"
,
keys
)
}
keys
=
kring
.
KeysById
(
0xfd94408d4543314f
)
if
len
(
keys
)
!=
1
||
keys
[
0
]
.
Entity
!=
kring
[
0
]
{
t
.
Errorf
(
"bad result for 0xa34d7e18c20c31bb: %#v"
,
keys
)
}
}
func
checkSignedMessage
(
t
*
testing
.
T
,
signedHex
,
expected
string
)
{
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2Hex
))
md
,
err
:=
ReadMessage
(
readerFromHex
(
signedHex
),
kring
,
nil
)
if
err
!=
nil
{
t
.
Error
(
err
)
return
}
if
!
md
.
IsSigned
||
md
.
SignedByKeyId
!=
0xa34d7e18c20c31bb
||
md
.
SignedBy
==
nil
||
md
.
IsEncrypted
||
md
.
IsSymmetricallyEncrypted
||
len
(
md
.
EncryptedToKeyIds
)
!=
0
||
md
.
IsSymmetricallyEncrypted
{
t
.
Errorf
(
"bad MessageDetails: %#v"
,
md
)
}
contents
,
err
:=
ioutil
.
ReadAll
(
md
.
UnverifiedBody
)
if
err
!=
nil
{
t
.
Errorf
(
"error reading UnverifiedBody: %s"
,
err
)
}
if
string
(
contents
)
!=
expected
{
t
.
Errorf
(
"bad UnverifiedBody got:%s want:%s"
,
string
(
contents
),
expected
)
}
if
md
.
SignatureError
!=
nil
||
md
.
Signature
==
nil
{
t
.
Error
(
"failed to validate: %s"
,
md
.
SignatureError
)
}
}
func
TestSignedMessage
(
t
*
testing
.
T
)
{
checkSignedMessage
(
t
,
signedMessageHex
,
signedInput
)
}
func
TestTextSignedMessage
(
t
*
testing
.
T
)
{
checkSignedMessage
(
t
,
signedTextMessageHex
,
signedTextInput
)
}
func
TestSignedEncryptedMessage
(
t
*
testing
.
T
)
{
expected
:=
"Signed and encrypted message
\n
"
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2PrivateHex
))
prompt
:=
func
(
keys
[]
Key
,
symmetric
bool
)
([]
byte
,
os
.
Error
)
{
if
symmetric
{
t
.
Errorf
(
"prompt: message was marked as symmetrically encrypted"
)
return
nil
,
error
.
KeyIncorrectError
}
if
len
(
keys
)
==
0
{
t
.
Error
(
"prompt: no keys requested"
)
return
nil
,
error
.
KeyIncorrectError
}
err
:=
keys
[
0
]
.
PrivateKey
.
Decrypt
([]
byte
(
"passphrase"
))
if
err
!=
nil
{
t
.
Errorf
(
"prompt: error decrypting key: %s"
,
err
)
return
nil
,
error
.
KeyIncorrectError
}
return
nil
,
nil
}
md
,
err
:=
ReadMessage
(
readerFromHex
(
signedEncryptedMessageHex
),
kring
,
prompt
)
if
err
!=
nil
{
t
.
Errorf
(
"error reading message: %s"
,
err
)
return
}
if
!
md
.
IsSigned
||
md
.
SignedByKeyId
!=
0xa34d7e18c20c31bb
||
md
.
SignedBy
==
nil
||
!
md
.
IsEncrypted
||
md
.
IsSymmetricallyEncrypted
||
len
(
md
.
EncryptedToKeyIds
)
==
0
||
md
.
EncryptedToKeyIds
[
0
]
!=
0x2a67d68660df41c7
{
t
.
Errorf
(
"bad MessageDetails: %#v"
,
md
)
}
contents
,
err
:=
ioutil
.
ReadAll
(
md
.
UnverifiedBody
)
if
err
!=
nil
{
t
.
Errorf
(
"error reading UnverifiedBody: %s"
,
err
)
}
if
string
(
contents
)
!=
expected
{
t
.
Errorf
(
"bad UnverifiedBody got:%s want:%s"
,
string
(
contents
),
expected
)
}
if
md
.
SignatureError
!=
nil
||
md
.
Signature
==
nil
{
t
.
Error
(
"failed to validate: %s"
,
md
.
SignatureError
)
}
}
func
TestUnspecifiedRecipient
(
t
*
testing
.
T
)
{
expected
:=
"Recipient unspecified
\n
"
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2PrivateHex
))
md
,
err
:=
ReadMessage
(
readerFromHex
(
recipientUnspecifiedHex
),
kring
,
nil
)
if
err
!=
nil
{
t
.
Errorf
(
"error reading message: %s"
,
err
)
return
}
contents
,
err
:=
ioutil
.
ReadAll
(
md
.
UnverifiedBody
)
if
err
!=
nil
{
t
.
Errorf
(
"error reading UnverifiedBody: %s"
,
err
)
}
if
string
(
contents
)
!=
expected
{
t
.
Errorf
(
"bad UnverifiedBody got:%s want:%s"
,
string
(
contents
),
expected
)
}
}
func
TestSymmetricallyEncrypted
(
t
*
testing
.
T
)
{
expected
:=
"Symmetrically encrypted.
\n
"
prompt
:=
func
(
keys
[]
Key
,
symmetric
bool
)
([]
byte
,
os
.
Error
)
{
if
len
(
keys
)
!=
0
{
t
.
Errorf
(
"prompt: len(keys) = %d (want 0)"
,
len
(
keys
))
}
if
!
symmetric
{
t
.
Errorf
(
"symmetric is not set"
)
}
return
[]
byte
(
"password"
),
nil
}
md
,
err
:=
ReadMessage
(
readerFromHex
(
symmetricallyEncryptedCompressedHex
),
nil
,
prompt
)
if
err
!=
nil
{
t
.
Errorf
(
"ReadMessage: %s"
,
err
)
return
}
contents
,
err
:=
ioutil
.
ReadAll
(
md
.
UnverifiedBody
)
if
err
!=
nil
{
t
.
Errorf
(
"ReadAll: %s"
,
err
)
}
expectedCreatationTime
:=
uint32
(
1295992998
)
if
md
.
LiteralData
.
Time
!=
expectedCreatationTime
{
t
.
Errorf
(
"LiteralData.Time is %d, want %d"
,
md
.
LiteralData
.
Time
,
expectedCreatationTime
)
}
if
string
(
contents
)
!=
expected
{
t
.
Errorf
(
"contents got: %s want: %s"
,
string
(
contents
),
expected
)
}
}
func
testDetachedSignature
(
t
*
testing
.
T
,
kring
KeyRing
,
signature
io
.
Reader
,
sigInput
,
tag
string
)
{
signed
:=
bytes
.
NewBufferString
(
sigInput
)
signer
,
err
:=
CheckDetachedSignature
(
kring
,
signed
,
signature
)
if
err
!=
nil
{
t
.
Errorf
(
"%s: signature error: %s"
,
tag
,
err
)
return
}
if
signer
==
nil
{
t
.
Errorf
(
"%s: signer is nil"
)
return
}
expectedSignerKeyId
:=
uint64
(
0xa34d7e18c20c31bb
)
if
signer
.
PrimaryKey
.
KeyId
!=
expectedSignerKeyId
{
t
.
Errorf
(
"%s: wrong signer got:%x want:%x"
,
signer
.
PrimaryKey
.
KeyId
,
expectedSignerKeyId
)
}
}
func
TestDetachedSignature
(
t
*
testing
.
T
)
{
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2Hex
))
testDetachedSignature
(
t
,
kring
,
readerFromHex
(
detachedSignatureHex
),
signedInput
,
"binary"
)
testDetachedSignature
(
t
,
kring
,
readerFromHex
(
detachedSignatureTextHex
),
signedInput
,
"text"
)
}
const
signedInput
=
"Signed message
\n
line 2
\n
line 3
\n
"
const
signedTextInput
=
"Signed message
\r\n
line 2
\r\n
line 3
\r\n
"
const
recipientUnspecifiedHex
=
"848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b"
const
detachedSignatureHex
=
"889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77"
const
detachedSignatureTextHex
=
"889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39"
const
testKeys1And2Hex
=
"988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003"
const
testKeys1And2PrivateHex
=
"9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000"
const
signedMessageHex
=
"a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
const
signedTextMessageHex
=
"a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
const
signedEncryptedMessageHex
=
"848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d"
const
symmetricallyEncryptedCompressedHex
=
"8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6"
src/pkg/crypto/openpgp/write.go
0 → 100644
View file @
6ca009f5
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
openpgp
import
(
"crypto"
"crypto/openpgp/armor"
"crypto/openpgp/error"
"crypto/openpgp/packet"
"crypto/rsa"
_
"crypto/sha256"
"io"
"os"
"strconv"
"time"
)
// DetachSign signs message with the private key from signer (which must
// already have been decrypted) and writes the signature to w.
func
DetachSign
(
w
io
.
Writer
,
signer
*
Entity
,
message
io
.
Reader
)
os
.
Error
{
return
detachSign
(
w
,
signer
,
message
,
packet
.
SigTypeBinary
)
}
// ArmoredDetachSign signs message with the private key from signer (which
// must already have been decrypted) and writes an armored signature to w.
func
ArmoredDetachSign
(
w
io
.
Writer
,
signer
*
Entity
,
message
io
.
Reader
)
(
err
os
.
Error
)
{
return
armoredDetachSign
(
w
,
signer
,
message
,
packet
.
SigTypeBinary
)
}
// DetachSignText signs message (after canonicalising the line endings) with
// the private key from signer (which must already have been decrypted) and
// writes the signature to w.
func
DetachSignText
(
w
io
.
Writer
,
signer
*
Entity
,
message
io
.
Reader
)
os
.
Error
{
return
detachSign
(
w
,
signer
,
message
,
packet
.
SigTypeText
)
}
// ArmoredDetachSignText signs message (after canonicalising the line endings)
// with the private key from signer (which must already have been decrypted)
// and writes an armored signature to w.
func
SignTextDetachedArmored
(
w
io
.
Writer
,
signer
*
Entity
,
message
io
.
Reader
)
os
.
Error
{
return
armoredDetachSign
(
w
,
signer
,
message
,
packet
.
SigTypeText
)
}
func
armoredDetachSign
(
w
io
.
Writer
,
signer
*
Entity
,
message
io
.
Reader
,
sigType
packet
.
SignatureType
)
(
err
os
.
Error
)
{
out
,
err
:=
armor
.
Encode
(
w
,
SignatureType
,
nil
)
if
err
!=
nil
{
return
}
err
=
detachSign
(
out
,
signer
,
message
,
sigType
)
if
err
!=
nil
{
return
}
return
out
.
Close
()
}
func
detachSign
(
w
io
.
Writer
,
signer
*
Entity
,
message
io
.
Reader
,
sigType
packet
.
SignatureType
)
(
err
os
.
Error
)
{
if
signer
.
PrivateKey
==
nil
{
return
error
.
InvalidArgumentError
(
"signing key doesn't have a private key"
)
}
if
signer
.
PrivateKey
.
Encrypted
{
return
error
.
InvalidArgumentError
(
"signing key is encrypted"
)
}
sig
:=
new
(
packet
.
Signature
)
sig
.
SigType
=
sigType
sig
.
PubKeyAlgo
=
signer
.
PrivateKey
.
PubKeyAlgo
sig
.
Hash
=
crypto
.
SHA256
sig
.
CreationTime
=
uint32
(
time
.
Seconds
())
sig
.
IssuerKeyId
=
&
signer
.
PrivateKey
.
KeyId
h
,
wrappedHash
,
err
:=
hashForSignature
(
sig
.
Hash
,
sig
.
SigType
)
if
err
!=
nil
{
return
}
io
.
Copy
(
wrappedHash
,
message
)
switch
signer
.
PrivateKey
.
PubKeyAlgo
{
case
packet
.
PubKeyAlgoRSA
,
packet
.
PubKeyAlgoRSASignOnly
:
priv
:=
signer
.
PrivateKey
.
PrivateKey
.
(
*
rsa
.
PrivateKey
)
err
=
sig
.
SignRSA
(
h
,
priv
)
default
:
err
=
error
.
UnsupportedError
(
"public key algorithm: "
+
strconv
.
Itoa
(
int
(
sig
.
PubKeyAlgo
)))
}
if
err
!=
nil
{
return
}
return
sig
.
Serialize
(
w
)
}
src/pkg/crypto/openpgp/write_test.go
0 → 100644
View file @
6ca009f5
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
openpgp
import
(
"bytes"
"testing"
)
func
TestSignDetached
(
t
*
testing
.
T
)
{
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2PrivateHex
))
out
:=
bytes
.
NewBuffer
(
nil
)
message
:=
bytes
.
NewBufferString
(
signedInput
)
err
:=
DetachSign
(
out
,
kring
[
0
],
message
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
testDetachedSignature
(
t
,
kring
,
out
,
signedInput
,
"check"
)
}
func
TestSignTextDetached
(
t
*
testing
.
T
)
{
kring
,
_
:=
ReadKeyRing
(
readerFromHex
(
testKeys1And2PrivateHex
))
out
:=
bytes
.
NewBuffer
(
nil
)
message
:=
bytes
.
NewBufferString
(
signedInput
)
err
:=
DetachSignText
(
out
,
kring
[
0
],
message
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
testDetachedSignature
(
t
,
kring
,
out
,
signedInput
,
"check"
)
}
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