-
Notifications
You must be signed in to change notification settings - Fork 162
feat: Enforce EDV document ID format in EDVFormatProvider #2263
feat: Enforce EDV document ID format in EDVFormatProvider #2263
Conversation
An explanation of why this is needed: While working on the EDV REST provider, I realized an issue with the approach I was taking. The spec says that the ID in a structured document and encrypted document MUST be a Base58-encoded 128-bit random value. This PR provides a solution to that problem while still allowing the client to use a "regular" non-Base58-encoded 128-bit random value. Here's how it works:
This generic indexing+querying approach should work with the upcoming EDV REST provider and any other providers that support querying. @sandrask @troyronda And anyone else who reviews this: let me know what you think of this approach. |
@@ -38,10 +43,24 @@ var ( | |||
|
|||
type marshalFunc func(interface{}) ([]byte, error) | |||
|
|||
type MACComputer interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize this name is a little bit funny. Let me know if you have any suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MACDigester
is better as we are usually talking about a message digest when referring to Mac.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
4a5381e
to
57eeefe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved. Messy workaround necessary - request to remove this document ID constraint from the spec was filed a while ago: https://github.com/decentralized-identity/secure-data-store/issues/112
@@ -734,7 +734,7 @@ func (m *mockStore) Delete(k string) error { | |||
return m.delete(k) | |||
} | |||
|
|||
func (m *mockStore) Query(query string) (storage.StoreIterator, error) { | |||
func (m *mockStore) Query(indexKey string, indexValue string) (storage.StoreIterator, error) { | |||
return m.query(query) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
query
argument is not refactored following the signature change above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
57eeefe
to
e19bd2e
Compare
Codecov Report
@@ Coverage Diff @@
## master #2263 +/- ##
==========================================
- Coverage 89.90% 89.87% -0.03%
==========================================
Files 226 226
Lines 15103 15158 +55
==========================================
+ Hits 13579 13624 +45
- Misses 903 908 +5
- Partials 621 626 +5
Continue to review full report at Codecov.
|
e19bd2e
to
4d0b3d4
Compare
// DocumentProcessor represents a type that can encrypt and decrypt between | ||
// Structured Documents and Encrypted Documents. | ||
type DocumentProcessor interface { | ||
Encrypt(*edv.StructuredDocument) (*edv.EncryptedDocument, error) | ||
Encrypt(*edv.StructuredDocument, []edv.IndexedAttributeCollection) (*edv.EncryptedDocument, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noticed these issues:
- DocumentProcessor is inside the
edv/formatprovider
package instead of being a first-classstorage
citizen (like we discussed previously). To recall: the "document processor" encrypts all artifacts into a standard form and would be reused with other storage implementations - It looks like the documentprocessor does not encrypt the indexed attribute collection. Does it really need to be an argument? It's not even returned from
Decrypt()
, so there is an asymmetry here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The DocumentProcessor is used by the EDVFormatProvider, which allows the EDV format to be reused with any other storage implementation. There's no need for a "standard form".
- The indexed attributes are hashed before being passed in to the DocumentProcessor. This is what allows the documents to be queried. This allows us to still get documents based on a key per the usual provider method signature, so from the outside, an EDVFormatProvider (with whatever underlying provider you want) still works the same as any other provider. StructuredDocuments don't have encrypted indices, so they aren't returned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, I could create some sort of even more general DocumentProcessor class that just assumes JWE as what's being used for encryption. Or I could make it even more general and have it deal with just []byte. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just realized one potentially confusing thing: the EDV spec calls them "Encrypted Indices", although they're actually HMACed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the EDVFormatProvider will still require the more specific DocumentProcessor that deals with Structured and Encrypted Documents per the spec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, I could create some sort of even more general DocumentProcessor class that just assumes JWE as what's being used for encryption. Or I could make it even more general and have it deal with just []byte. What do you think?
Last time we agreed we'd use the EDV format across all stores. The format would be pluggable, thus we'd have an "edv format" and potentially other formats. All would adhere to some common interface. This interface would a first-class citizen under storage
or somewhere not far from it.
I guess we can regroup on monday.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Output of monday's session will be a GitHub issue with the high-level tasks and design of pluggable encrypted formats that can be reused across all store implementations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrote down general direction here: #2199 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created an issue and added a ToDo above the FormatProvider: #2273
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My next PR will be to generalize this FormatProvider. This will involve moving it out of the edv
folder and moving logic around to different places
4a1aad5
to
f69d2ff
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's first discuss this PR's direction as indicated here
3cffc81
to
2cd41c3
Compare
macCrypto *MACCrypto | ||
indexKeyMACBase64Encoded string | ||
marshal marshalFunc | ||
randomBytesFunc generateRandomBytesFunc | ||
} | ||
|
||
func (s formatStore) Put(k string, v []byte) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why isn't formatStore a pointer receiver (i.e., *formatStore)?
when in doubt, use a pointer receiver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's a mistake. I had originally fixed it in this PR (you'll see it if you go back a few force-commits), but since I'll be moving this entire file per #2263 (comment), I figured that it would make more sense to keep this PR small and fix it in the next one. I'll make a note in that issue to fix it so that I don't miss it.
Signed-off-by: Derek Trider <Derek.Trider@securekey.com>
2cd41c3
to
b51ab9a
Compare
Signed-off-by: Derek Trider Derek.Trider@securekey.com
also closes #2228