--- Log opened Tue Jan 28 00:00:22 2020 00:03 -!- real_or_random [~real_or_r@2a02:c207:3002:7468::1] has quit [Ping timeout: 248 seconds] 00:13 < sipa> adding more data to the nonce derivation should never hurt, if the assumptions on the input hold 00:13 < sipa> so clearly adding pubkey data to the derivation never hurts when that pubkey data is correct 00:14 < sipa> and whether we standardize/expose a way to use it with pubkey passed in can depend on 00:14 < sipa> how much confidence we have in that 00:16 -!- real_or_random [~smuxi@HSI-KBW-091-089-171-009.hsi2.kabel-badenwuerttemberg.de] has joined #secp256k1 00:17 < real_or_random> hm, my bnc is broken, so I couldn't read your responses here (if any) 00:17 < real_or_random> anyway, I'll post to the github issue, seems easier 00:18 < real_or_random> sipa: ah now you posted there... that's my point basically 00:25 < sipa> real_or_random: i've left a bunch more comments 00:26 < real_or_random> yep, I see :D 00:26 < real_or_random> all your three comments popped up while I was typing mine 00:41 < elichai2> Was asleep but FWIW for all the 4-5 implementations I've checked yesterday *none* of them inputted the pubkey into the nonce function, they just inputted the second half of H512(x) and the message 00:42 < gmaxwell> FWIW, https://moderncrypto.org/mail-archive/curves/2020/001012.html 00:42 < real_or_random> elichai2: did they all store the public key along with the secret key? 00:42 < gmaxwell> I got an offlist reply from https://github.com/w3f/schnorrkel/issues/53 00:43 < elichai2> Real_or_random Nope. Got it as input 00:43 < elichai2> Although dalek *has the option* to store them together 00:43 < real_or_random> ter 00:44 < real_or_random> *there's also https://github.com/jedisct1/libsodium/issues/170 00:45 < real_or_random> which says that NaCl and libsodium stores the public key as part of the secret key 00:47 < gmaxwell> I didn't look at nacl or libsodium but nothing I looked at did that. In particular, ed25519-donna doesn't and I think it's by far the most commonly used code. 00:47 < gmaxwell> https://github.com/floodyberry/ed25519-donna/blob/master/test.c#L150 00:48 < real_or_random> re synthetic nonces: yes, I think everybody should use this 00:51 < elichai2> real_or_random: the NaCl mirror I found in github didn't hash the pubkey into the challange at all :O 00:52 < elichai2> That's not ed25519 compatible, probably old code or something, I'll download from djb website 00:52 < sipa> elichai2: none do 00:52 < sipa> elichai2: the question is whether the pubkey fed to the signing code can come from untrusted sources 00:52 < elichai2> sipa: challange, not nonce 00:53 < sipa> elichai2: wut 00:53 < sipa> ah, non-keyprefixed eddsa 00:53 < sipa> that sounds very old 00:53 < elichai2> Probably, it's some random mirror on github (still on my phone lol) 00:54 * sipa zZzZ 00:54 < sipa> sorry 00:54 * sipa Schnorrs 00:54 < real_or_random> >.> 01:00 < elichai2> I think libsosium is the same?! :O https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_sign/ed25519/ref10/sign.c#L93 I don't see any mention of pubkey. Maybe I'm in the wrong place?! I'll grep it in half an hour 01:01 < gmaxwell> elichai2: the libsodium stuff is not compatible with the published ed25519 stuff. 01:01 < elichai2> gmaxwell: so they just don't prefix the pubkey? 01:04 < gmaxwell> elichai2: it doesn't. 01:09 < gmaxwell> I see no warning about this in RFC 8032, and the python library stuck in the RFC has the pubkey as a seperate argument. 01:10 < gmaxwell> more interesting challenge is going to find something thats actually vulnerable due to this. 01:11 < gmaxwell> likely target would be something that logically only signs with one key, but would recieve a pubkey over the network as part of its signing request. 01:11 < gmaxwell> and uses any conformant ed25519 implementation (not libsodium). 01:14 < real_or_random> gmaxwell: did you see my comment on github that explains why it potentially affects our use more than the normal signatures? 01:16 < gmaxwell> yes. though thats fixed easily by adding the flip boolean to the nonce input. 01:16 < gmaxwell> there is a lot less reason someone would send that over the network normally though. 01:19 < real_or_random> I'm talking about https://github.com/sipa/bips/issues/190#issuecomment-579133223 01:22 < gmaxwell> oh sweet. well at least there the key your signature is valid for is explicit right there. 01:23 < gmaxwell> that isn't just us, however. there are other places where tweaked keys are used. e.g. thats how tor v3 hidden services work. 01:23 < gmaxwell> though because there is essentially just one implementation of that written by people who actually understand cryptography, I doubt it'll have issues. 01:31 < gmaxwell> aside, googling around for bip32 ed25519 turns up a fair amount of stuff. 01:31 < gmaxwell> most of it is awful. 01:36 < gmaxwell> okay, I found a demo app that appears to have both vulnerabilities. basically it takes a signing request as a json object and deserializes it. and the derrivation code works by checking if each field (like child public key) is present before computing it. 01:37 < gmaxwell> and its nonce function is a standard ed25519 one. 01:37 < gmaxwell> though it's just a stupid demo app. 01:56 * gmaxwell makes a mental note to never use security software written in rust, these people are all crazy. 02:07 < real_or_random> sample size 1? :P 02:11 < gmaxwell> no, I've sent emails for four vulnerablities unrelated to stuff we're discussing in here, as a side effect of googling to try to find examples of stuff with the vulnerablities we've been discussing here. I was particuarly horrified by a bunch of the rust crates I bumped into, which looked like bad machine generated C code fed into a food processor before being machine transformed into rust. 02:13 < gmaxwell> I give up, it's too hard to find examples of _this_ vulnerablity because I keep finding other ones that I need to report. 02:13 < gmaxwell> I no longer believe derandomized signing is safer than random numbers. :P 02:18 < real_or_random> lol 02:39 -!- belcher [~belcher@unaffiliated/belcher] has joined #secp256k1 03:49 -!- k3tan [~ketan@unaffiliated/k3tan] has joined #secp256k1 03:57 < elichai2> gmaxwell: I'm curious about the rust crates :) there's a bunch of non-cryptographers writing shitty cryptography code (see https://github.com/paritytech/libsecp256k1 which failed to translate libsecp and even sometimes translated bitwise AND into logical AND). 04:00 -!- real_or_random [~smuxi@HSI-KBW-091-089-171-009.hsi2.kabel-badenwuerttemberg.de] has quit [Read error: Connection reset by peer] 04:22 < gmaxwell> I especially like where they make their internal types visible to the outside, and then callers end up getting wrong values from dealing with unnormalized field elements. (not that the callers have any way to normalize them, mind you) 04:23 < gmaxwell> I can just imagine the authors going around and telling people that libsecp256k1 code is broken... except they seem to be concealing that they're apeing it entirely, even though they're going as far as copying out the comments verbatim. 04:25 < gmaxwell> the 4.5MB of constants dumped into the source files are amusing too. 04:28 -!- jonasschnelli [~jonasschn@unaffiliated/jonasschnelli] has joined #secp256k1 04:33 -!- IRC-Source_26 [5d6ccfd7@gateway/web/cgi-irc/kiwiirc.com/ip.93.108.207.215] has joined #secp256k1 04:38 -!- IRC-Source_26 [5d6ccfd7@gateway/web/cgi-irc/kiwiirc.com/ip.93.108.207.215] has quit [Remote host closed the connection] 04:59 -!- zac94 [528267cf@ee-tik-dhcp-103-207.ethz.ch] has joined #secp256k1 08:53 -!- RubenSomsen [sid301948@gateway/web/irccloud.com/x-ychgpeigdrmerrwf] has quit [] 08:54 -!- RubenSomsen [sid301948@gateway/web/irccloud.com/x-bwhyuyenhxtslndx] has joined #secp256k1 10:10 < sipa> gmaxwell: i assume you saw djb's response 10:11 < sipa> verifying the signature that comes out is a good suggestion, and maybe we should mention explicitly too 10:11 < sipa> as it not only protects against invalid pubkeys, but also against fault attacks 10:12 < sipa> of course... i don't think any of the ed25519 apis do that either 10:14 < sipa> his tagging argument... i think is confused 10:14 < sipa> it also seems unrelated (and i don't really agree with it anyway) 10:32 < roconnor> Isn't verifying the signature at least as expensive than computing the pubkey from the secret key? 10:37 < sipa> yes 10:37 < sipa> well, variable time algorithms 10:38 < sipa> but also a multi-mult 10:38 < sipa> i wonder if you can't share part of the computation 10:42 < sipa> roconnor: to be clear, i'm not suggesting verifying signatures instead of including pubkey data in the nonce derivation; just as an independent point 10:58 < roconnor> Right. I'm just noting that the argument seems to be to add a pubkey argument to the signing function to safe time, but to make the API safe, lets run a verify step on the resulting signature. 10:59 < roconnor> Though I admit that not quiet the argument being made here. But it is close :D 10:59 < sipa> roconnor: ah, you're right - but verifying the signature that comes out protects against more than the passed-in pubkey being wrong 11:00 < roconnor> That is true. 11:47 -!- zac94 [528267cf@ee-tik-dhcp-103-207.ethz.ch] has quit [Remote host closed the connection] 12:37 < elichai2> I think we talked about this in the past. But why can't we use the same keygen trick musig does (with the musig coefficients) but on the nonce generation to remove a round? 12:38 < elichai2> I'll assume that if Wagner is applicable here it could also be applicable at key generation 12:38 < elichai2> Real_or_random 12:39 < sipa> elichai2: well the neven paper proved that it is impossible to prove secure any 2-round schnorr multisig protocol in DL 12:39 < sipa> even OMDL, iirc 12:40 < sipa> so i'm not going to bother trying :p 12:40 < sipa> elichai2: with deterministic nonces it does seem possible, though 12:41 < elichai2> I'm saying even without. Using musig coefficients. Wait I'll open the neven paper again, I don't think they said it can't be done. Just that everything currently out there is broken 12:42 < elichai2> They even present their own 2 round scheme 12:44 < sipa> if you mean the okamoto based scheme, yes, that's two rounds... but bigger pubkeys 12:45 < elichai2> Yes. So it's not Impossible 12:45 < sipa> it is impossible for schnorr 12:45 < sipa> but they have a meta reduction that proves such a proof cannot work, i believe 12:46 < sipa> they had that before they actually found an attack against 2-round musig 12:47 < elichai2> Hmm right they say "to prove that there cannot be a security proof for CoSi in the ROM under OMDL assumption" 12:48 < elichai2> It still feel like if the musig keygen is secure then it should be secure for the nonce 12:49 < elichai2> Altough here there's yet another hash it's getting fed into (the challange) so maybe that's where wagner's can crawl (nickler) 12:51 < sipa> i'm often amazed by provable security 12:52 < sipa> it regularly seems that the proof technique requires these totally arbitrary-seeming requirements 12:52 < sipa> and then later you learn that without them, there is an actual attack 12:52 < sipa> and sometikes not 12:53 < elichai2> I still don't understand provable security good enough :/ I should really read all the recommendations people gave me on Twitter when I asked lol 12:54 < sipa> elichai2: btw, there is no proof (afaik) that 2-round multischnorr is inherently insecure 12:54 < sipa> only that you can't prove it secure under rom/(om)dl 12:55 < elichai2> Right. So I wonder how will you prove purify+BP for deterministic, it's again just rom+dlg 12:55 < sipa> nope, it has additional assumptions 12:55 < elichai2> BP has more assumptions than just dlg? 12:55 < sipa> (ddh in two other grouos( 12:56 < sipa> no, but our purify+BP scheme assumes DDH hardness in two other EC groups 12:56 < elichai2> I'll guess purify is the one assuming ddh 12:56 < elichai2> Ha 12:56 < sipa> yeah 12:56 < elichai2> Almost pairing ? 13:00 < gmaxwell> sipa: I like verfiying... if you don't care about performance... it's slow. 13:03 < gmaxwell> I'm a bit confused by his response, his own code presents an api that seperates them. 13:04 < gmaxwell> but whatever, it's okay enough. He acknoweldges it would be useful to include. 13:05 < elichai2> sipa: I think this is interesting https://crysp.uwaterloo.ca/software/frost/frost-techreport-20200120.pdf they also assume DDH 13:06 < gmaxwell> has no one gotten them to retract that yet? it's totally busted. 13:06 < gmaxwell> it's kind of mystifying. 13:07 < elichai2> gmaxwell: the Frost paper? 13:07 < gmaxwell> yes. 13:07 < gmaxwell> as it's the completely naieve algorithim you'd write if you were completely unaware of the existance of the attacks that make accomplishing that difficult in the first place. 13:08 < elichai2> Reading now reading and looking for problems, I thought they said they're doing it with DLG only 13:08 < elichai2> gmaxwell: you mean secure broadcast? 13:08 < gmaxwell> no, the protocol is essentially just "use interpolation for keys, nonces, and signatures." 13:09 < gmaxwell> It's vulnerable to the attacks musig was created to correct. 13:09 < elichai2> Rouge key attack? 13:09 < elichai2> How? 13:10 < gmaxwell> e.g. https://medium.com/blockstream/insecure-shortcuts-in-musig-2ad0d38a97da 13:12 < elichai2> Oh you mean wagners, that what I was trying to see, if they're vulnerable to wagners and where 13:13 < gmaxwell> it's also rogue keyable too, it's easiest when you consider the N of N case, in which case the secret sharing just reduces to "add the keys". 13:15 < gmaxwell> A good thing when reviewing papers is to look for citations to the attacks it ought to be defending against. 13:15 < gmaxwell> it's a sign that this field is communicating extremely poorly. 13:16 < elichai2> But you can't see other people's keys 13:16 < gmaxwell> Sure you can, the "public commitment" is the pubkey. (It's a verifyable secret share) 13:17 < elichai2> In pederson he uses pederson commitments 13:19 < elichai2> Hmm their figure 1 does seem look like they mean public keys and not pederson 13:19 < gmaxwell> look at the key generation, it's two rounds. That doesn't make room for an extra step for opening. 14:11 < roconnor> sipa: I don't have any strong opinions about new tags; but FWIW, I've been using ascii character 0x1F as my separator symbol. 14:12 < roconnor> That's said, I've been largely using it because I think no one else would be foolish enough to do so as well, ensuring the uniqueness of my own tags. 14:18 < nickler> elichai2: for one "musig in the nonces" doesn't work because last signer to choose their nonce can bias the output of the challenge hash which enables the well known wagner attack 14:25 < gmaxwell> sipa: one downside of verify after signing is that you need a verify context. 14:26 < gmaxwell> a thought I had is that we could do verify after signing unless a flag is passed via context. It's slow as hell, but many applications don't care. 14:26 < gmaxwell> I don't really like "generate the pubkey" as a belt-and-suspenders, even if you don't care about performance, because it increases your sidechannel surface. 14:28 < gmaxwell> I'm kinda debating asking him to show me one implementation of ed25519 that doesn't take the pubkey as an agument. The closest I found was one where it was embedded in the private key, which I agree is a big improvement, but also still not obviously safe. 14:29 < gmaxwell> but OTOH it doesn't matter, I'm just mystified by his mystification. 14:29 < sipa> yes, me too 14:29 < sipa> it's obvious why implementers choose the shortcut of taking in the pubkey... because it avoids recomputing it 14:30 < gmaxwell> turns out that if you can _double_ yor performance with a simple change, many people will. :) which kinda sounds like DJB's historic arguments for curves where the complete group law is also the fastest. 14:30 < gmaxwell> except instead of being a 1% difference it's a doubling. 14:31 < sipa> his argument is consistent with thinking that private keys should be passed around in a privkey+pubkey combined structure, though 14:33 < gmaxwell> but the important thing is that he agreed that hashing the pubkey is prudent. Though he makes it conditional "if there is this exposure then", which I think is just fragile. Like in secp256k1's bipschnorr we didn't have the exposure, but then later wanted to change the interface. Fortunately, we're mired in nonce attack considerations due to musig and noticed the problem. 14:34 < gmaxwell> I do like privkey+pubkey combined, but I don't think it's a complete fix. You still have callers that will work around your interface for good reasons like key derrivation. 14:34 < gmaxwell> part of his perspective difference might also be because ed25519 needs a keygen step more complicated than "choose 32 random bytes" 14:35 < gmaxwell> you have to reduce it to 255 bits, set the highest bit, and clear the lowest three bits. 15:17 -!- real_or_random [~smuxi@p5DEAAED5.dip0.t-ipconnect.de] has joined #secp256k1 15:30 < real_or_random> sipa: so it seems that people want to prefer savings in the signing algorithm over very small savings in verification? 15:33 < sipa> real_or_random: i think it's not unreasonable to consider both negligible in most circumstances... but adding the gratuitious complication of integration with existing BIP32-based infrastructure maybe tips it over in favor of odd/even 15:34 < sipa> though if you put it like that... a 5 us savings at sign time vs a 10 ns slowdown of verification is probably worth it on itself too 15:36 < real_or_random> that's what I'm saying 15:37 < real_or_random> I mean we usually care much more about verification speed but maybe not in the nanosecond range 15:37 < sipa> yup 15:37 < roconnor> I was going to suggest that 1 signature is worth 1000 verification, which arguably tips things in the other direction. :D 15:39 < sipa> roconnor: i am struggling to argue why the ratio of hypothetical speed tradeoffs between signing and verification should be below 1000, but i feel that it is 15:39 < sipa> a tradeoff that doubles signing time while making verification 0.1% faster seems crazy 15:40 < sipa> but i have no good argument why 15:40 < real_or_random> roconnor: that's a valid argument. if we want to optimize for overall computation time in the system 15:41 < sipa> note that these things do run on different types of hardware 15:41 < sipa> in practice 15:41 < real_or_random> right 15:41 < real_or_random> but don't ask me what we optimize for in the end 15:41 < sipa> and signing is generally done on mostly unloaded systems, while verification runs on loaded systems 15:42 < sipa> (which is another argument to prioritize verification time) 15:44 < real_or_random> the signing speedup is around 1% on my system (which is very different from a hardware wallet of course) 15:45 < sipa> right, but if we care about some "minimizing total computation" (not sure that's the right metric), when taking hardware wallets into account, this may well mean gaining 1 ms at signing time vs losing 10 ns at verification time 15:46 < sipa> all things considered, i think that yes, the ratio is large enough here that we should favor the signer, but i can't really articulate the argument i'm using to determine that 15:49 < real_or_random> did you attend jp's RWC talk? :P 15:50 < sipa> yes 15:50 < nickler> real_or_random: on my laptop it's more than 6% (3.5us) 15:50 < real_or_random> that seems odd 15:50 < real_or_random> (or squared?) 15:51 < sipa> 5% seems not unreasonable; the number i have in my head is 5us for a jacobi symbol, and signing in total is less than 100us 15:51 < real_or_random> hm 15:51 < sipa> with GMP-based jacobi symbol it's faster 15:51 < real_or_random> nickler: what are your numbers? 15:51 < real_or_random> oh yeah, maybe I have gmp enabled 15:51 < sipa> but that one is variable time... is that safe to use here even? 15:51 < nickler> real_or_random: 53.5 vs 57.0 15:52 < real_or_random> and num_jacobi? 15:52 < real_or_random> ok, I guess the difference 15:54 < roconnor> sipa: I don't actually have strong opinions on the matter. 15:54 < roconnor> my 1000:1 was just loosely based on the number of times I expect a bitcoin signature to be verified. 15:55 < real_or_random> sipa: there should be secrets involved for either pk and R 15:55 < roconnor> but I totally agree that hardware wallets are somewhat of a factor here. 15:55 < roconnor> Anyhow, no strong opinion from me. 15:56 < sipa> real_or_random: if (!secp256k1_fe_is_quad_var(&pk.y)) { 15:57 < sipa> given that it's being applied to the public key, this should be fine 15:57 < real_or_random> right, and R is equally public 15:57 < sipa> an attacker can know pk.y 16:00 < nickler> real_or_random: yeah apparently I'm using NUM_NONE and therefore secp256k1_fe_sqrt (4.5us) instead of num_jacobi 16:01 < real_or_random> I think an argument that one can make is that it's a good idea to write a spec that does not favor one operation hugely over the other, and then if you care about nanoseconds, please optimize the implementation 16:02 < real_or_random> or cut half of the rounds of SHA256 :P 16:07 < elichai2> What about *returning* the pubkey from the sign algorithm? That way if a user need both to Calc pubkey and to sign he can just sign and get it 16:07 < elichai2> I mean it doesn't solve it all(eg if the user already has the pubkey stored) 16:07 < sipa> elichai2: that's too late :p 16:08 < sipa> i see what you mean 16:08 < sipa> i don't know if it's relevant in practice 16:08 < elichai2> We both not accept untrusted pubkeys and we give users the ability to "not waste computation" 16:09 < elichai2> sipa: we should look at some hw wallets code to check (and/or ask them hehe) 16:09 < sipa> right, but in say in psbt setting, i suspect anything will have computed the pubkey in advance, just to verify against the pubkey entry in hd_keypaths field 16:10 < elichai2> Hmm it's a tradeoff on what you want first, but yeah you probably don't want a signature laying around if you realized it was the wrong key 16:30 -!- real_or_random [~smuxi@p5DEAAED5.dip0.t-ipconnect.de] has quit [Ping timeout: 268 seconds] 16:51 < gmaxwell> on signing vs verification ratio: for use in bitcoin transactions the ratio should probably be >>1000x. But even within the ecosystem these things do get used outside of just transactions. 16:51 < gmaxwell> Consider, for example, a musig aggregation. One reasonable way to handle byzantine fault it to concurrently sign with every subset that includes you. 16:51 < gmaxwell> so now you're potentially doing 10,000 signatures to sign one message. 16:52 < gmaxwell> it would be kinda sad to slow that down by a huge amount just to save a bit on verification. 16:54 < gmaxwell> I'm a little dubious about using hardware wallet speed as an argument, there isn't a particularly strong reason why the existing ones are quite as slow as they are (esp given their sticker price), except that that was all that was required. 16:56 < gmaxwell> for comparison, consider the USB armory, a hardware wallet sized usb stick computer with a 900MHz arm a7 and a half gig of ram that sells for a vaguely hardware wallet price. ($150). 16:58 < gmaxwell> also, to be clear, this jacobi cost is _keygen_ not signing. 16:58 < gmaxwell> applications which would care about getting high signing message rates don't tend to care about high keygen rates. 16:59 < gmaxwell> sipa: I think we can prove num_jacobi is fine. You're already multiplied by z 16:59 < sipa> gmaxwell: agree, though your valgrind based checker will complain 16:59 < sipa> i guess we'd just explicitly mark the output initialized 17:00 < gmaxwell> thats what declassify is for. 17:00 < gmaxwell> also the operation can be blinded very cheaply, if you're worried. 17:01 < gmaxwell> just multiply it with a random number with a known jacobi symbol. 17:02 < gmaxwell> I already had that PR about blinding that inverse. 17:02 < gmaxwell> FWIW, it seems that using a blinded inverse is ubiquitious in other people's crypto code, we're unusual in using a constant time inverse. 17:03 < gmaxwell> (not that I saw a lot of other things I would want to emulate...) 17:03 < sipa> i think our primary reason for using a constant time inverse is that it's easier to implement :) 17:03 < sipa> (significantly) 17:03 < sipa> especially when you don't already have generic big number support 17:03 < gmaxwell> It is for our field, they're harder when it isn't congrent to 3 mod 4 I guess. 17:04 < sipa> right 17:08 < gmaxwell> another argument for favoring verrification is that there isn't much to be done to speed up verification that we're aware of (beyond porting all the group law to make SIMD versions, or similar). 17:09 < gmaxwell> While signing there are a number of _easy_ speedups: use a cheaper nonce function hash, use a larger precomputation table, batch construct nonces randomly (so to share the inverses for affine projection; which also makes the signing latency extremely low, <1us)... 17:10 < sipa> another argument that favors verification is that if you really care about signing time, there are (not without complexity costs) solutions that trivially reduce it (using precomputed k/R values) 17:10 < sipa> s/trivially/massively/ 17:10 < gmaxwell> for verification I think the low hanging speedups are: wait some months and ship endomorphism, use batches, SIMD SQRT for your batches, then SIMD group law for the pippenger. then ???? only the first two are relatively easy and we're mostly benchmarking assuming them already. 17:11 < gmaxwell> oh signing also has the "use a blinded instead of constant time inverse" as a potential easy speedup. 17:12 < gmaxwell> also for the "non bitcoin applications" that tend to be the things that care most about singing speed there is the option of USE SOMETHING ELSE. 17:12 < gmaxwell> A nice GLV/GLS curve, for example. 18:00 -!- belcher [~belcher@unaffiliated/belcher] has quit [Quit: Leaving] --- Log closed Wed Jan 29 00:00:23 2020