Reputation: 4891
I am trying to establish a TLS connection by providing a tls.Config
struct containing a Rand
field that should always return the same int
when calling their Read
method, cf. the docs here: https://golang.org/pkg/crypto/tls/#Config
I've written this builder:
func newZeroRand() *rand.Rand {
return rand.New(rand.NewSource(0))
}
And a test to make sure that rand.Rand
is always returning the same int
when Read
is invkoed multiple times, notice the different input params "foo"
and "bar"
providing the same output:
func TestPredictableZeroRandGenerator(t *testing.T) {
zeroRand := newZeroRand()
firstNum, err := zeroRand.Read([]byte("foo"))
if err != nil {
t.Error(err)
}
secondNum, err := zeroRand.Read([]byte("bar"))
if err != nil {
t.Error(err)
}
// fmt.Printf("firstNum %d secondNum %d \n", firstNum, secondNum)
if firstNum != secondNum {
t.Error(fmt.Sprintf("This is not a predictable zero random generator! The first number is: %d the second number is: %d", firstNum, secondNum))
}
}
Using that previously defined newZeroRand()
I was expecting to generate always the same SSL key inside the file same-key.log
when providing the TLS configuration like this:
func tlsConfig() (*tls.Config, error) {
w, err := os.OpenFile("same-key.log", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return nil, err
}
tlsConfig := tls.Config{
Rand: newZeroRand(),
KeyLogWriter: w,
}
return &tlsConfig, nil
}
But for multiple executions I get different file contents. I may be misunderstanding the details here: https://golang.org/pkg/crypto/tls/#example_Config_keyLogWriter because when I open those files same-key.log
after each execution
then I find the structure described here in the NSS Key Log Format from Mozilla: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
CLIENT_RANDOM <FIRST_LONG_ID> <SECOND_LONG_ID>
where:
<FIRST_LONG_ID>
is always the same<SECOND_LONG_ID>
is changing after each execution <-- why this is happening?When providing a key file same-key.log
for a batch of packets from a different execution, then Wireshark is not able to decrpyt them!
I may be misunderstanding some internals about SSL cryptography here and I was wondering if I should also provide the certificates in the configuration struct? How could I generate these certificates?
Afaik when using certificates on top of the key there should be a piece of information coming from the other side at runtime, so then I can not decrypt the stream of packets if I don't have that information. This is why I thought certificates are not needed if I want to use Wireshark to decrypt those packets.
Otherwise I am not sure how could I force the TCP connection to always encrypt/decrypt the packets with the same key?
Edit:
As pointed out by @peter in his answer I was asserting on the length of the input byte slice rather than the actual "deterministic-random value".
I came out with this Read
implementation for the tls.Config
struct:
type debugRand struct {}
func (dr *debugRand) Read(p []byte) (n int, err error) {
for i := range p {
p[i] = byte(0)
}
return len(p), nil
}
func newZeroRand() *debugRand {
return &debugRand{}
}
This is setting to 0
all the elements of the input slice.
However I still generate SSL keys which have different <SECOND_LONG_ID>
values for different executions.
Is it possible at all to get Wireshark re-using SSL keys on different TLS connections when analysing those encrypted TCP packets?
Upvotes: 2
Views: 2355