Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add signing and encryption #1025

Closed
wants to merge 172 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
172 commits
Select commit Hold shift + click to select a range
924987e
x509: Parse signature algorithm
bookmoons May 2, 2019
8658192
x509: Stringify unknown signature algorithm
bookmoons May 2, 2019
b8b29b4
x509: Parse certificate subject
bookmoons May 3, 2019
f5aeaaf
x509: Parse postal code
bookmoons May 3, 2019
26ae498
x509: Parse province
bookmoons May 3, 2019
817aa16
x509: Parse locality
bookmoons May 3, 2019
486989f
x509: Parse street address
bookmoons May 3, 2019
9729576
x509: Parse organization
bookmoons May 3, 2019
1a55042
x509: Parse organizational units
bookmoons May 3, 2019
62c678e
x509: Parse subject common name
bookmoons May 3, 2019
6d507e7
x509: Qualify subject error messages
bookmoons May 3, 2019
12ef550
x509: Parse issuer country
bookmoons May 3, 2019
66ebce6
x509: Parse issuer province
bookmoons May 3, 2019
5a5c09f
x509: Parse issuer locality
bookmoons May 3, 2019
ccbad81
x509: Parse issuer organization
bookmoons May 3, 2019
8c6badf
Add missing semicolon
bookmoons May 3, 2019
0f2a328
x509: Parse issuer common name
bookmoons May 3, 2019
794f219
x509: Parse lower bound
bookmoons May 3, 2019
686d5fe
x509: Parse upper bound
bookmoons May 3, 2019
f989961
x509: Parse alternate names
bookmoons May 3, 2019
7c0f298
x509: Parse fingerprint
bookmoons May 3, 2019
f2f5452
x509: Rename countryName country
bookmoons May 3, 2019
e9a09cd
x509: Remove subtest name redundancy
bookmoons May 3, 2019
d3b5f41
x509: Parse public key algorithm
bookmoons May 3, 2019
f69cd25
x509: Skip on short test
bookmoons May 3, 2019
26775d6
x509: Parse public key exponent
bookmoons May 3, 2019
288e1e4
x509: Parse public key modulus
bookmoons May 3, 2019
59486b3
x509: Factor test material
bookmoons May 3, 2019
a05c1d1
x509: Add getIssuer
bookmoons May 3, 2019
ab3c4de
x509: Add getSubject
bookmoons May 3, 2019
316b459
x509: Add getAltNames
bookmoons May 3, 2019
6833737
Uncapitalize error strings
bookmoons May 3, 2019
1f806dd
Wipe up lint
bookmoons May 3, 2019
189daa5
Make internal functions unexported
bookmoons May 3, 2019
67f9b47
Wipe up lint
bookmoons May 3, 2019
ffd9edf
Correct formatting
bookmoons May 3, 2019
305b6ac
x509: Accept SHA-1 use
bookmoons May 7, 2019
7e4f5bf
x509: Correct comment
bookmoons May 9, 2019
c1f7d53
x509: Factor JavaScript error throwing
bookmoons May 9, 2019
11d4538
x509: Isolate JavaScript error throwing
bookmoons May 9, 2019
cfb9d7a
x509: Use error wrapping
bookmoons May 9, 2019
26ab8df
x509: Check error message
bookmoons May 9, 2019
4eedcfc
x509: Lowercase utility functions
bookmoons May 9, 2019
446734c
x509: Add test material structure
bookmoons May 9, 2019
248e424
x509: Test parse failure of valid PEM
bookmoons May 9, 2019
2802dc4
x509: Add subject names
bookmoons May 10, 2019
7af94e1
x509: Add issuer names
bookmoons May 10, 2019
4d8098c
x509: Detect names in shortcut methods
bookmoons May 10, 2019
5006ab9
x509: Move public key algorithm to certificate root
bookmoons May 10, 2019
12d89a1
x509: Use combined public key in certificate
bookmoons May 10, 2019
4e0c899
x509: Add DSA public key parsing
bookmoons May 10, 2019
84e10db
x509: Add ECDSA public key parsing
bookmoons May 10, 2019
1d55323
Format code
bookmoons May 10, 2019
14806cb
x509: Minimize type assertions
bookmoons May 10, 2019
dac9da9
Correct formatting
bookmoons May 15, 2019
cb3fabe
x509: Move algorithm into public key
bookmoons May 15, 2019
3a13e19
x509: Abstract public key
bookmoons May 15, 2019
67b97b8
x509: Allow test material global
bookmoons May 15, 2019
40d513f
x509: Accept encoded certificate as []byte
bookmoons May 16, 2019
f2bbb77
x509: Test signature algorithm
bookmoons May 16, 2019
793ee98
x509: Test make public key
bookmoons May 16, 2019
99e08b7
x509: Test make certificate
bookmoons May 16, 2019
44cfa25
x509: Correct make certificate return
bookmoons May 16, 2019
1a1a27d
x509: Preserve certificate parsing error
bookmoons May 8, 2019
ead4a35
x509: Qualify certificate subject
bookmoons May 8, 2019
6655649
x509: Add parsePublicKey
bookmoons May 8, 2019
1d26c24
x509: Capitalize acronym in test name
bookmoons May 8, 2019
b7485c8
x509: Correct test name
bookmoons May 8, 2019
257af2b
x509: add parsePrivateKey
bookmoons May 8, 2019
b74d8e5
x509: Test with identical private keys
bookmoons May 8, 2019
0d9fb85
x509: Simplify test material routine names
bookmoons May 9, 2019
d916cce
x509: Add test material struct
bookmoons May 9, 2019
8f49a21
crypto: Add SHA256 message hashing
bookmoons May 9, 2019
1df51cd
crypto: Add signature decoding
bookmoons May 9, 2019
ed9fcd7
sign: Qualify expected digest values
bookmoons May 9, 2019
13e499c
sign: Add hash function decoding
bookmoons May 9, 2019
9ef7135
sign: Add PKCS verification
bookmoons May 9, 2019
a53a07a
sign: Add PSS verification
bookmoons May 9, 2019
ef10547
sign: Add PKCS signing
bookmoons May 9, 2019
853e7c8
sign: Improve error message
bookmoons May 9, 2019
3968bde
Correct formatting
bookmoons May 9, 2019
8df994b
sign: Add PSS signing
bookmoons May 9, 2019
1f04364
x509: Correct test material field name
bookmoons May 10, 2019
3053331
Correct merge errors
bookmoons May 10, 2019
7ab7847
x509: Test DSA public key parsing
bookmoons May 10, 2019
70ffb4a
x509: Test ECDSA public key parsing
bookmoons May 10, 2019
e52096a
sign: Reorder test material
bookmoons May 10, 2019
d9fe766
sign: Describe type SigningOptions
bookmoons May 10, 2019
c41772c
sign: Add verifier creation
bookmoons May 10, 2019
1565bbc
sign: Test hex output
bookmoons May 10, 2019
c35d0d8
sign: Test base64 output
bookmoons May 10, 2019
a072362
sign: Test binary output
bookmoons May 10, 2019
91bd4ed
sign: Test default output
bookmoons May 10, 2019
ec31dbb
sign: Generalize data decode routine
bookmoons May 10, 2019
90ba704
sign: Accept arbitrary signature types
bookmoons May 10, 2019
3fe0fe8
sign: Factor hex decoding
bookmoons May 10, 2019
25e6e1b
sign: Factor base64 decoding
bookmoons May 10, 2019
22ebada
sign: Factor string data decoding
bookmoons May 10, 2019
79058e9
sign: Rename decodeData* decodeBinary*
bookmoons May 10, 2019
4071e9e
sign: Rename encodeSignature encodeBinary
bookmoons May 10, 2019
719363e
crypto: Factor binary encoding
bookmoons May 10, 2019
842b968
crypto: Centralize test utility functions
bookmoons May 10, 2019
d5b5f18
crypto: Correct variable name
bookmoons May 10, 2019
520d5be
crypto: Test binary encoding
bookmoons May 10, 2019
6e3d9b7
crypto: Test encode with unsupported format
bookmoons May 10, 2019
18800e5
crypto: Define binary decoding
bookmoons May 10, 2019
fbe0089
crypto: Correct byte array decoding
bookmoons May 10, 2019
fb628b0
sign: Test input signature encodings
bookmoons May 10, 2019
5aeafc2
Format code
bookmoons May 10, 2019
5918709
crypto: Define string to binary decoding
bookmoons May 11, 2019
d9897d2
crypto: Reorder decoding routines
bookmoons May 11, 2019
bee0515
crypto: Remote string to binary decoding
bookmoons May 11, 2019
e46623e
sign: Deal with plaintext as binary
bookmoons May 11, 2019
8c32386
crypto: Factor test utility functions
bookmoons May 11, 2019
6f8d7f6
sign: Remove context from internal functions
bookmoons May 11, 2019
8bca57e
sign: Throw JavaScript errors in prepareSign
bookmoons May 11, 2019
1318d2b
Prefer context pointers
bookmoons May 11, 2019
e9bb1f7
Prefer pointer receivers
bookmoons May 11, 2019
d27279f
sign: Store context with verifier
bookmoons May 11, 2019
b68cb96
sign: Add verifier functionality
bookmoons May 11, 2019
2139cdc
sign: Add Signer
bookmoons May 11, 2019
ce5d76b
sign: Document signer
bookmoons May 11, 2019
866c351
sign: Add context to decoding errors
bookmoons May 11, 2019
e7521f6
sign: Add string message verification
bookmoons May 11, 2019
376700d
sign: Add string message signing
bookmoons May 11, 2019
c41bbcd
sign: Lowercase hash function encodings
bookmoons May 11, 2019
47dc419
crypto: Factor hash function execution
bookmoons May 11, 2019
a17a6db
crypto: Factor hasher construction
bookmoons May 11, 2019
0341ffa
crypto: Simplify hash execution routine
bookmoons May 11, 2019
6dc0f3a
sign: Use existing hashing
bookmoons May 11, 2019
dcbb947
sign: Add DSA verification
bookmoons May 11, 2019
36eca74
sign: Add DSA signing
bookmoons May 11, 2019
2df4e02
sign: Add ECDSA verification
bookmoons May 11, 2019
5ccbb52
sign: Add ECDSA signing
bookmoons May 11, 2019
3d19b9b
crypto: Correct rebase errors
bookmoons May 15, 2019
70f7517
sign: Validate public key
bookmoons May 15, 2019
a857ed1
x509: Move algorithm into private key
bookmoons May 15, 2019
70d0ff8
x509: Abstract private key
bookmoons May 15, 2019
02f311b
crypt: Validate private key
bookmoons May 15, 2019
1e38e25
sign: Allow test material global
bookmoons May 15, 2019
23c3ad1
Merge branch 'master' into bookmoons/sign
bookmoons May 17, 2019
7147edf
Correct merge error
bookmoons May 17, 2019
c324660
sign: Add algorithm constants
bookmoons May 19, 2019
9885b7e
sign: Remove unused test utility
bookmoons May 19, 2019
81e848b
sign: Allow test material global
bookmoons May 19, 2019
92d9e5b
sign: Simplify useless assignment
bookmoons May 19, 2019
0176876
crypto: Accept blacklisted hash functions
bookmoons May 19, 2019
5ac78d3
sign: Simplify declaration with known type
bookmoons May 19, 2019
070dc30
sign: Simplify boolean returns
bookmoons May 19, 2019
4737fa6
sign: Make constants private
bookmoons May 19, 2019
e2fc072
sign: Correct constants
bookmoons May 19, 2019
dbf97c5
x509: Add parsePublicKey
bookmoons May 8, 2019
5a660ab
x509: Add parsePublicKey
bookmoons May 8, 2019
33c73c3
Correct merge errors
bookmoons May 10, 2019
3d2b802
Format code
bookmoons May 10, 2019
9408b3a
crypto: Centralize throw routine
bookmoons May 11, 2019
f9bab5e
crypto: Add utility section
bookmoons May 11, 2019
1367e12
crypto: Centralize function decoding
bookmoons May 11, 2019
e73e7fa
crypto: Factor test material
bookmoons May 11, 2019
42c1687
sign: Correct return value
bookmoons May 11, 2019
683c69c
encrypt: Add PKCS decryption
bookmoons May 11, 2019
7efcf91
crypto: Factor unsupported signing function detection
bookmoons May 12, 2019
8b31922
crypto: Centralize unsupported hash function detection
bookmoons May 12, 2019
02be68d
encrypt: Add OAEP decryption
bookmoons May 12, 2019
9146384
encrypt: Add labeled OAEP decryption
bookmoons May 12, 2019
6b73ec4
crypto: Add string decoding
bookmoons May 12, 2019
30125d8
encrypt: Add string decryption
bookmoons May 12, 2019
c5107cb
encrypt: Add PKCS encryption
bookmoons May 12, 2019
d595fc3
encrypt: Add OAEP encryption
bookmoons May 12, 2019
8dd1f38
encrypt: Add labeled OAEP encryption
bookmoons May 12, 2019
60f70e5
encrypt: Add string encryption
bookmoons May 12, 2019
45bc2e6
Correct rebase errors
bookmoons May 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions js/modules/k6/crypto/code.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
*
* k6 - a next-generation load testing tool
* Copyright (C) 2019 Load Impact
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package crypto

import (
"encoding/base64"
"encoding/hex"
"unicode/utf8"

"github.com/pkg/errors"
)

func decodeBinary(encoded interface{}, format string) ([]byte, error) {
if format != "" {
return decodeBinaryKnown(encoded, format)
}
return decodeBinaryDetect(encoded)
}

func decodeBinaryKnown(encoded interface{}, format string) ([]byte, error) {
switch format {
case "binary":
return decodeBytes(encoded)
case "hex":
return decodeHex(encoded)
case "base64":
return decodeBase64(encoded)
default:
err := errors.New("unsupported binary encoding: " + format)
return nil, err
}
}

func decodeBinaryDetect(encoded interface{}) ([]byte, error) {
decoded, err := decodeBytes(encoded)
if err == nil {
return decoded, nil
}
decoded, err = decodeHex(encoded)
if err == nil {
return decoded, nil
}
decoded, err = decodeBase64(encoded)
if err == nil {
return decoded, nil
}
err = errors.New("unrecognized binary encoding")
return nil, err
}

func decodeBytes(abstracted interface{}) ([]byte, error) {
switch encoded := abstracted.(type) {
case []uint8:
return decodeInternalBytes(encoded), nil
case []interface{}:
return decodeExternalBytes(encoded)
default:
err := errors.New("not a byte array")
return nil, err
}
}

// Bytes originating in Go unmarshaled as slice of uint8
func decodeInternalBytes(encoded []uint8) []byte {
return []byte(encoded)
}

// Bytes originating in JavaScript unmarshaled as slice of abstracted int64
func decodeExternalBytes(encoded []interface{}) ([]byte, error) {
decoded := make([]byte, len(encoded))
for i, itemAbstracted := range encoded {
itemDecoded, err := decodeExternalByte(itemAbstracted)
if err != nil {
return nil, err
}
decoded[i] = itemDecoded
}
return decoded, nil
}

func decodeExternalByte(abstracted interface{}) (byte, error) {
encoded, ok := abstracted.(int64)
if !ok {
err := errors.New("not a byte array")
return 0, err
}
return byte(encoded), nil
}

func decodeHex(abstracted interface{}) ([]byte, error) {
encoded, ok := abstracted.(string)
if !ok {
err := errors.New("not a hex string")
return nil, err
}
return hex.DecodeString(encoded)
}

func decodeBase64(abstracted interface{}) ([]byte, error) {
encoded, ok := abstracted.(string)
if !ok {
err := errors.New("not a base64 string")
return nil, err
}
return base64.StdEncoding.DecodeString(encoded)
}

func decodeString(encoded []byte) (string, error) {
if !utf8.Valid(encoded) {
err := errors.New("not a UTF-8 string")
return "", err
}
return string(encoded), nil
}

func encodeBinary(value []byte, format string) (interface{}, error) {
switch format {
case "":
fallthrough
case "binary":
return value, nil
case "hex":
encoded := hex.EncodeToString(value)
return encoded, nil
case "base64":
encoded := base64.StdEncoding.EncodeToString(value)
return encoded, nil
default:
err := errors.New("unsupported binary encoding: " + format)
return "", err
}
}
146 changes: 146 additions & 0 deletions js/modules/k6/crypto/code_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
*
* k6 - a next-generation load testing tool
* Copyright (C) 2019 Load Impact
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package crypto

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestDecodeBinaryKnown(t *testing.T) {
t.Run("Unsupported", func(t *testing.T) {
_, err := decodeBinaryKnown([]byte{1, 2, 3}, "nucleaonic")
assert.EqualError(t, err, "unsupported binary encoding: nucleaonic")
})

t.Run("ByteArrayValid", func(t *testing.T) {
value := []interface{}{
interface{}(int64(1)),
interface{}(int64(2)),
interface{}(int64(3)),
}
result, err := decodeBinaryKnown(value, "binary")
assert.NoError(t, err)
assert.Equal(t, []byte{1, 2, 3}, result)
})

t.Run("ByteArrayInvalid", func(t *testing.T) {
_, err := decodeBinaryKnown("010203", "binary")
assert.EqualError(t, err, "not a byte array")
})

t.Run("HexValid", func(t *testing.T) {
result, err := decodeBinaryKnown("010203", "hex")
assert.NoError(t, err)
assert.Equal(t, []byte{1, 2, 3}, result)
})

t.Run("HexInvalid", func(t *testing.T) {
_, err := decodeBinaryKnown([]byte{1, 2, 3}, "hex")
assert.EqualError(t, err, "not a hex string")
})

t.Run("Base64Valid", func(t *testing.T) {
result, err := decodeBinaryKnown("AQID", "base64")
assert.NoError(t, err)
assert.Equal(t, []byte{1, 2, 3}, result)
})

t.Run("Base64Invalid", func(t *testing.T) {
_, err := decodeBinaryKnown([]byte{1, 2, 3}, "base64")
assert.EqualError(t, err, "not a base64 string")
})
}

func TestDecodeBinaryDetect(t *testing.T) {
t.Run("Unrecognized", func(t *testing.T) {
_, err := decodeBinaryDetect("bad-binary")
assert.EqualError(t, err, "unrecognized binary encoding")
})

t.Run("ByteArray", func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add another test that verifies that if you pass a greater-than-255 value in the array, it will be an error

value := []interface{}{
interface{}(int64(1)),
interface{}(int64(2)),
interface{}(int64(3)),
}
result, err := decodeBinaryDetect(value)
assert.NoError(t, err)
assert.Equal(t, []byte{1, 2, 3}, result)
})

t.Run("Hex", func(t *testing.T) {
result, err := decodeBinaryDetect("010203")
assert.NoError(t, err)
assert.Equal(t, []byte{1, 2, 3}, result)
})

t.Run("Base64", func(t *testing.T) {
result, err := decodeBinaryDetect("AQID")
assert.NoError(t, err)
assert.Equal(t, []byte{1, 2, 3}, result)
})
}

func TestDecodeString(t *testing.T) {
t.Run("Invalid", func(t *testing.T) {
_, err := decodeString([]byte{0xc3, 0x28})
assert.EqualError(t, err, "not a UTF-8 string")
})

t.Run("Valid", func(t *testing.T) {
result, err := decodeString([]byte("tallyho"))
assert.NoError(t, err)
assert.Equal(t, "tallyho", result)
})
}

func TestEncodeBinary(t *testing.T) {
t.Run("Unsupported", func(t *testing.T) {
_, err := encodeBinary([]byte{1, 2, 3}, "nucleonic")
assert.EqualError(t, err, "unsupported binary encoding: nucleonic")
})

t.Run("Default", func(t *testing.T) {
result, err := encodeBinary([]byte{1, 2, 3}, "")
assert.NoError(t, err)
assert.Equal(t, []byte{1, 2, 3}, result)
})

t.Run("ByteArray", func(t *testing.T) {
result, err := encodeBinary([]byte{1, 2, 3}, "binary")
assert.NoError(t, err)
assert.Equal(t, []byte{1, 2, 3}, result)
})

t.Run("Hex", func(t *testing.T) {
result, err := encodeBinary([]byte{1, 2, 3}, "hex")
assert.NoError(t, err)
assert.Equal(t, "010203", result)
})

t.Run("Base64", func(t *testing.T) {
result, err := encodeBinary([]byte{1, 2, 3}, "base64")
assert.NoError(t, err)
assert.Equal(t, "AQID", result)
})
}
Loading