blob: eb22b1d318f5e1c65fa984e7e403ee1c164bafa7 [file] [log] [blame]
/*-
* Copyright 2014 Square Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jose
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"errors"
"io"
"testing"
)
func TestEd25519(t *testing.T) {
_, err := newEd25519Signer("XYZ", nil)
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
enc := new(edEncrypterVerifier)
enc.publicKey = ed25519PublicKey
err = enc.verifyPayload([]byte{}, []byte{}, "XYZ")
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
dec := new(edDecrypterSigner)
dec.privateKey = ed25519PrivateKey
_, err = dec.signPayload([]byte{}, "XYZ")
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
sig, err := dec.signPayload([]byte("This is a test"), "EdDSA")
if err != nil {
t.Error("should not error trying to sign payload")
}
if sig.Signature == nil {
t.Error("Check the signature")
}
err = enc.verifyPayload([]byte("This is a test"), sig.Signature, "EdDSA")
if err != nil {
t.Error("should not error trying to verify payload")
}
err = enc.verifyPayload([]byte("This is test number 2"), sig.Signature, "EdDSA")
if err == nil {
t.Error("should not error trying to verify payload")
}
}
func TestInvalidAlgorithmsRSA(t *testing.T) {
_, err := newRSARecipient("XYZ", nil)
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
_, err = newRSASigner("XYZ", nil)
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
enc := new(rsaEncrypterVerifier)
enc.publicKey = &rsaTestKey.PublicKey
_, err = enc.encryptKey([]byte{}, "XYZ")
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
err = enc.verifyPayload([]byte{}, []byte{}, "XYZ")
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
dec := new(rsaDecrypterSigner)
dec.privateKey = rsaTestKey
_, err = dec.decrypt(make([]byte, 256), "XYZ", randomKeyGenerator{size: 16})
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
_, err = dec.signPayload([]byte{}, "XYZ")
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
}
type failingKeyGenerator struct{}
func (ctx failingKeyGenerator) keySize() int {
return 0
}
func (ctx failingKeyGenerator) genKey() ([]byte, rawHeader, error) {
return nil, rawHeader{}, errors.New("failed to generate key")
}
func TestPKCSKeyGeneratorFailure(t *testing.T) {
dec := new(rsaDecrypterSigner)
dec.privateKey = rsaTestKey
generator := failingKeyGenerator{}
_, err := dec.decrypt(make([]byte, 256), RSA1_5, generator)
if err != ErrCryptoFailure {
t.Error("should return error on invalid algorithm")
}
}
func TestInvalidAlgorithmsEC(t *testing.T) {
_, err := newECDHRecipient("XYZ", nil)
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
_, err = newECDSASigner("XYZ", nil)
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
enc := new(ecEncrypterVerifier)
enc.publicKey = &ecTestKey256.PublicKey
_, err = enc.encryptKey([]byte{}, "XYZ")
if err != ErrUnsupportedAlgorithm {
t.Error("should return error on invalid algorithm")
}
}
func TestInvalidECKeyGen(t *testing.T) {
gen := ecKeyGenerator{
size: 16,
algID: "A128GCM",
publicKey: &ecTestKey256.PublicKey,
}
if gen.keySize() != 16 {
t.Error("ec key generator reported incorrect key size")
}
_, _, err := gen.genKey()
if err != nil {
t.Error("ec key generator failed to generate key", err)
}
}
func TestInvalidECDecrypt(t *testing.T) {
dec := ecDecrypterSigner{
privateKey: ecTestKey256,
}
generator := randomKeyGenerator{size: 16}
// Missing epk header
headers := rawHeader{}
headers.set(headerAlgorithm, ECDH_ES)
_, err := dec.decryptKey(headers, nil, generator)
if err == nil {
t.Error("ec decrypter accepted object with missing epk header")
}
// Invalid epk header
headers.set(headerEPK, &JSONWebKey{})
_, err = dec.decryptKey(headers, nil, generator)
if err == nil {
t.Error("ec decrypter accepted object with invalid epk header")
}
}
func TestDecryptWithIncorrectSize(t *testing.T) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Error(err)
return
}
dec := new(rsaDecrypterSigner)
dec.privateKey = priv
aes := newAESGCM(16)
keygen := randomKeyGenerator{
size: aes.keySize(),
}
payload := make([]byte, 254)
_, err = dec.decrypt(payload, RSA1_5, keygen)
if err == nil {
t.Error("Invalid payload size should return error")
}
payload = make([]byte, 257)
_, err = dec.decrypt(payload, RSA1_5, keygen)
if err == nil {
t.Error("Invalid payload size should return error")
}
}
func TestPKCSDecryptNeverFails(t *testing.T) {
// We don't want RSA-PKCS1 v1.5 decryption to ever fail, in order to prevent
// side-channel timing attacks (Bleichenbacher attack in particular).
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Error(err)
return
}
dec := new(rsaDecrypterSigner)
dec.privateKey = priv
aes := newAESGCM(16)
keygen := randomKeyGenerator{
size: aes.keySize(),
}
for i := 1; i < 50; i++ {
payload := make([]byte, 256)
_, err := io.ReadFull(rand.Reader, payload)
if err != nil {
t.Error("Unable to get random data:", err)
return
}
_, err = dec.decrypt(payload, RSA1_5, keygen)
if err != nil {
t.Error("PKCS1v1.5 decrypt should never fail:", err)
return
}
}
}
func BenchmarkPKCSDecryptWithValidPayloads(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
enc := new(rsaEncrypterVerifier)
enc.publicKey = &priv.PublicKey
dec := new(rsaDecrypterSigner)
dec.privateKey = priv
aes := newAESGCM(32)
b.StopTimer()
b.ResetTimer()
for i := 0; i < b.N; i++ {
plaintext := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, plaintext)
if err != nil {
panic(err)
}
ciphertext, err := enc.encrypt(plaintext, RSA1_5)
if err != nil {
panic(err)
}
keygen := randomKeyGenerator{
size: aes.keySize(),
}
b.StartTimer()
_, err = dec.decrypt(ciphertext, RSA1_5, keygen)
b.StopTimer()
if err != nil {
panic(err)
}
}
}
func BenchmarkPKCSDecryptWithInvalidPayloads(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
enc := new(rsaEncrypterVerifier)
enc.publicKey = &priv.PublicKey
dec := new(rsaDecrypterSigner)
dec.privateKey = priv
aes := newAESGCM(16)
keygen := randomKeyGenerator{
size: aes.keySize(),
}
b.StopTimer()
b.ResetTimer()
for i := 0; i < b.N; i++ {
plaintext := make([]byte, 16)
_, err = io.ReadFull(rand.Reader, plaintext)
if err != nil {
panic(err)
}
ciphertext, err := enc.encrypt(plaintext, RSA1_5)
if err != nil {
panic(err)
}
// Do some simple scrambling
ciphertext[128] ^= 0xFF
b.StartTimer()
_, err = dec.decrypt(ciphertext, RSA1_5, keygen)
b.StopTimer()
if err != nil {
panic(err)
}
}
}
func TestInvalidEllipticCurve(t *testing.T) {
signer256 := ecDecrypterSigner{privateKey: ecTestKey256}
signer384 := ecDecrypterSigner{privateKey: ecTestKey384}
signer521 := ecDecrypterSigner{privateKey: ecTestKey521}
_, err := signer256.signPayload([]byte{}, ES384)
if err == nil {
t.Error("should not generate ES384 signature with P-256 key")
}
_, err = signer256.signPayload([]byte{}, ES512)
if err == nil {
t.Error("should not generate ES512 signature with P-256 key")
}
_, err = signer384.signPayload([]byte{}, ES256)
if err == nil {
t.Error("should not generate ES256 signature with P-384 key")
}
_, err = signer384.signPayload([]byte{}, ES512)
if err == nil {
t.Error("should not generate ES512 signature with P-384 key")
}
_, err = signer521.signPayload([]byte{}, ES256)
if err == nil {
t.Error("should not generate ES256 signature with P-521 key")
}
_, err = signer521.signPayload([]byte{}, ES384)
if err == nil {
t.Error("should not generate ES384 signature with P-521 key")
}
}
func estInvalidECPublicKey(t *testing.T) {
// Invalid key
invalid := &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: elliptic.P256(),
X: fromBase64Int("MTEx"),
Y: fromBase64Int("MTEx"),
},
D: fromBase64Int("0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo"),
}
headers := rawHeader{}
headers.set(headerAlgorithm, ECDH_ES)
headers.set(headerEPK, &JSONWebKey{
Key: &invalid.PublicKey,
})
dec := ecDecrypterSigner{
privateKey: ecTestKey256,
}
_, err := dec.decryptKey(headers, nil, randomKeyGenerator{size: 16})
if err == nil {
t.Fatal("decrypter accepted JWS with invalid ECDH public key")
}
}
func TestInvalidAlgorithmEC(t *testing.T) {
err := ecEncrypterVerifier{publicKey: &ecTestKey256.PublicKey}.verifyPayload([]byte{}, []byte{}, "XYZ")
if err != ErrUnsupportedAlgorithm {
t.Fatal("should not accept invalid/unsupported algorithm")
}
}