def WriteSignedBinary(binary_urn: rdfvalue.RDFURN, binary_content: bytes, private_key: rdf_crypto.RSAPrivateKey, public_key: Optional[rdf_crypto.RSAPublicKey], chunk_size: int = 1024): """Signs a binary and saves it to the datastore. If a signed binary with the given URN already exists, its contents will get overwritten. Args: binary_urn: URN that should serve as a unique identifier for the binary. binary_content: Contents of the binary, as raw bytes. private_key: Key that should be used for signing the binary contents. public_key: Key that should be used to verify the signature generated using the private key. chunk_size: Size, in bytes, of the individual blobs that the binary contents will be split to before saving to the datastore. """ blob_references = rdf_objects.BlobReferences() for chunk_offset in range(0, len(binary_content), chunk_size): chunk = binary_content[chunk_offset:chunk_offset + chunk_size] blob_rdf = rdf_crypto.SignedBlob() blob_rdf.Sign(chunk, private_key, verify_key=public_key) blob_id = data_store.BLOBS.WriteBlobWithUnknownHash( blob_rdf.SerializeToBytes()) blob_references.items.Append( rdf_objects.BlobReference(offset=chunk_offset, size=len(chunk), blob_id=blob_id)) data_store.REL_DB.WriteSignedBinaryReferences( SignedBinaryIDFromURN(binary_urn), blob_references)
def WriteSignedBinaryBlobs(binary_urn, blobs, token=None): """Saves signed blobs to the datastore. If a signed binary with the given URN already exists, its contents will get overwritten. Args: binary_urn: RDFURN that should serve as a unique identifier for the binary. blobs: An Iterable of signed blobs to write to the datastore. token: ACL token to use with the legacy (non-relational) datastore. """ if _ShouldUseLegacyDatastore(): aff4.FACTORY.Delete(binary_urn, token=token) with data_store.DB.GetMutationPool() as mutation_pool: with aff4.FACTORY.Create(binary_urn, collects.GRRSignedBlob, mode="w", mutation_pool=mutation_pool, token=token) as fd: for blob in blobs: fd.Add(blob, mutation_pool=mutation_pool) if data_store.RelationalDBWriteEnabled(): blob_references = rdf_objects.BlobReferences() current_offset = 0 for blob in blobs: blob_id = data_store.BLOBS.WriteBlobWithUnknownHash( blob.SerializeToString()) blob_references.items.Append( rdf_objects.BlobReference(offset=current_offset, size=len(blob.data), blob_id=blob_id)) current_offset += len(blob.data) data_store.REL_DB.WriteSignedBinaryReferences( _SignedBinaryIDFromURN(binary_urn), blob_references)
def WriteHashBlobReferences(self, references_by_hash, cursor): """Writes blob references for a given set of hashes.""" values = [] for hash_id, blob_refs in iteritems(references_by_hash): refs = rdf_objects.BlobReferences(items=blob_refs).SerializeToString() values.append({ "hash_id": hash_id.AsBytes(), "blob_references": refs, }) _Insert(cursor, "hash_blob_references", values)
def WriteSignedBinary(binary_urn, binary_content, private_key, public_key, chunk_size=1024, token=None): """Signs a binary and saves it to the datastore. If a signed binary with the given URN already exists, its contents will get overwritten. Args: binary_urn: URN that should serve as a unique identifier for the binary. binary_content: Contents of the binary, as raw bytes. private_key: Key that should be used for signing the binary contents. public_key: Key that should be used to verify the signature generated using the private key. chunk_size: Size, in bytes, of the individual blobs that the binary contents will be split to before saving to the datastore. token: ACL token to use with the legacy (non-relational) datastore. """ if _ShouldUseLegacyDatastore(): collects.GRRSignedBlob.NewFromContent(binary_content, binary_urn, chunk_size=chunk_size, token=token, private_key=private_key, public_key=public_key) if data_store.RelationalDBWriteEnabled(): blob_references = rdf_objects.BlobReferences() for chunk_offset in range(0, len(binary_content), chunk_size): chunk = binary_content[chunk_offset:chunk_offset + chunk_size] blob_rdf = rdf_crypto.SignedBlob() blob_rdf.Sign(chunk, private_key, verify_key=public_key) blob_id = data_store.BLOBS.WriteBlobWithUnknownHash( blob_rdf.SerializeToString()) blob_references.items.Append( rdf_objects.BlobReference(offset=chunk_offset, size=len(chunk), blob_id=blob_id)) data_store.REL_DB.WriteSignedBinaryReferences( _SignedBinaryIDFromURN(binary_urn), blob_references)
def WriteSignedBinaryBlobs(binary_urn: rdfvalue.RDFURN, blobs: Iterable[rdf_crypto.SignedBlob]): """Saves signed blobs to the datastore. If a signed binary with the given URN already exists, its contents will get overwritten. Args: binary_urn: RDFURN that should serve as a unique identifier for the binary. blobs: An Iterable of signed blobs to write to the datastore. """ blob_references = rdf_objects.BlobReferences() current_offset = 0 for blob in blobs: blob_id = data_store.BLOBS.WriteBlobWithUnknownHash(blob.SerializeToBytes()) blob_references.items.Append( rdf_objects.BlobReference( offset=current_offset, size=len(blob.data), blob_id=blob_id)) current_offset += len(blob.data) data_store.REL_DB.WriteSignedBinaryReferences( _SignedBinaryIDFromURN(binary_urn), blob_references)
"""Tests for signed-binary DB functionality.""" from __future__ import absolute_import from __future__ import division from __future__ import unicode_literals from grr_response_server import db from grr_response_server.rdfvalues import objects as rdf_objects _test_id1 = rdf_objects.SignedBinaryID( binary_type=rdf_objects.SignedBinaryID.BinaryType.EXECUTABLE, path="linux/test/hello") _test_id2 = rdf_objects.SignedBinaryID( binary_type=rdf_objects.SignedBinaryID.BinaryType.PYTHON_HACK, path="windows/test/hello") _test_references1 = rdf_objects.BlobReferences(items=[ rdf_objects.BlobReference(offset=0, size=2, blob_id=b"\xaa" * 32), rdf_objects.BlobReference(offset=2, size=3, blob_id=b"\xbb" * 32), ]) _test_references2 = rdf_objects.BlobReferences(items=[ rdf_objects.BlobReference(offset=0, size=3, blob_id=b"\xcc" * 32), rdf_objects.BlobReference(offset=3, size=2, blob_id=b"\xdd" * 32), ]) class DatabaseTestSignedBinariesMixin(object): """Mixin that adds tests for signed binary DB functionality.""" def testReadSignedBinaryReferences(self): self.db.WriteSignedBinaryReferences(_test_id1, _test_references1) stored_hash_id, stored_timestamp = self.db.ReadSignedBinaryReferences( _test_id1) self.assertEqual(stored_hash_id, _test_references1) self.assertGreater(stored_timestamp.AsMicrosecondsSinceEpoch(), 0)