4545import com .microsoft .azure .storage .table .TableTestHelper .Class1 ;
4646import com .microsoft .azure .storage .table .TableTestHelper .EncryptedClass1 ;
4747import com .microsoft .azure .storage .table .TableTestHelper .ComplexEntity ;
48+ import com .sun .jersey .core .util .Base64 ;
4849
4950public class TableEncryptionTests {
5051 CloudTable table = null ;
@@ -457,6 +458,18 @@ private void doTableQueryDTEProjectionEncryption(TablePayloadFormat format, Symm
457458 assertTrue (ent .getProperties ().get ("A" ).getValueAsString ().equals ("a" )
458459 || ent .getProperties ().get ("A" ).getValueAsString ().equals (Constants .EMPTY_STRING ));
459460 }
461+
462+ // Test to make sure that we don't specify encryption columns when there aren't any columns specified at all.
463+ query = TableQuery .from (DynamicTableEntity .class );
464+
465+ for (DynamicTableEntity ent : this .table .execute (query , options , null )) {
466+ assertNotNull (ent .getPartitionKey ());
467+ assertNotNull (ent .getRowKey ());
468+ assertNotNull (ent .getTimestamp ());
469+
470+ assertTrue (ent .getProperties ().get ("A" ).getValueAsString ().equals ("a" )
471+ || ent .getProperties ().get ("A" ).getValueAsString ().equals (Constants .EMPTY_STRING ));
472+ }
460473 }
461474
462475 @ Test
@@ -1022,8 +1035,7 @@ public void testTableOperationEncryptionWithStrictModeOnMerge() throws InvalidKe
10221035 }
10231036
10241037 @ Test
1025- public void testTableOperationsIgnoreEncryption () throws InvalidKeyException , NoSuchAlgorithmException , NoSuchPaddingException , URISyntaxException , StorageException
1026- {
1038+ public void testTableOperationsIgnoreEncryption () throws InvalidKeyException , NoSuchAlgorithmException , NoSuchPaddingException , URISyntaxException , StorageException {
10271039 SymmetricKey aesKey = TestHelper .getSymmetricKey ();
10281040 TableRequestOptions options = new TableRequestOptions ();
10291041 options .setEncryptionPolicy (new TableEncryptionPolicy (aesKey , null ));
@@ -1072,6 +1084,65 @@ public void testTableOperationsIgnoreEncryption() throws InvalidKeyException, No
10721084 {
10731085 testTable .deleteIfExists ();
10741086 }
1087+ }
1088+
1089+ @ Test
1090+ public void testCrossPlatformCompatibility () throws StorageException , URISyntaxException {
1091+ CloudTable testTable = TableTestHelper .getRandomTableReference ();
1092+
1093+ try
1094+ {
1095+ testTable .createIfNotExists ();
1096+
1097+ // Hard code some sample data, then see if we can decrypt it.
1098+ // This key is used only for test, do not use to encrypt any sensitive data.
1099+ SymmetricKey sampleKEK = new SymmetricKey ("key1" , Base64 .decode ("rFz7+tv4hRiWdWUJMFlxl1xxtU/qFUeTriGaxwEcxjU=" ));
1100+
1101+ // This data here was created using Fiddler to capture the .NET library uploading an encrypted entity, encrypted with the specified KEK and CEK.
1102+ // Note that this data is lacking the library information in the KeyWrappingMetadata.
1103+ DynamicTableEntity dteNetOld = new DynamicTableEntity ("pk" , "netUp" );
1104+ dteNetOld .getProperties ().put ("sampleProp" , new EntityProperty (Base64 .decode ("27cLSlSFqy9C0xUCr57XAA==" )));
1105+ dteNetOld .getProperties ().put ("sampleProp2" , new EntityProperty (Base64 .decode ("pZR6Ln/DwbwyyOCEezL/hg==" )));
1106+ dteNetOld .getProperties ().put ("sampleProp3" , new EntityProperty (Base64 .decode ("JOix4N8eX/WuCtIvlD2QxQ==" )));
1107+ dteNetOld .getProperties ().put ("_ClientEncryptionMetadata1" , new EntityProperty ("{\" WrappedContentKey\" :{\" KeyId\" :\" key1\" ,\" EncryptedKey\" :\" pwSKxpJkwCS2zCaykh0m8e4OApeLuQ4FiahZ9zdwxaLL1HsWqQ4DSw==\" ,\" Algorithm\" :\" A256KW\" },\" EncryptionAgent\" :{\" Protocol\" :\" 1.0\" ,\" EncryptionAlgorithm\" :\" AES_CBC_256\" },\" ContentEncryptionIV\" :\" obTAQcYeFQ3IU7Jfcema7Q==\" ,\" KeyWrappingMetadata\" :{}}" ));
1108+ dteNetOld .getProperties ().put ("_ClientEncryptionMetadata2" , new EntityProperty (Base64 .decode ("MWA7LlvXSJnKhf8f7MVhfjWECkxrCyCXGIlYY6ucpr34IVDU7fN6IHvKxV15WiXp" )));
1109+
1110+ testTable .execute (TableOperation .insert (dteNetOld ));
1111+
1112+ // This data here was created using Fiddler to capture the Java library uploading an encrypted entity, encrypted with the specified KEK and CEK.
1113+ // Note that this data is lacking the KeyWrappingMetadata. It also constructs an IV with PK + RK + column name.
1114+ DynamicTableEntity dteJavaOld = new DynamicTableEntity ("pk" , "javaUp" );
1115+ dteJavaOld .getProperties ().put ("sampleProp" , new EntityProperty (Base64 .decode ("sa3bCvXq79ImSPveChS+cg==" )));
1116+ dteJavaOld .getProperties ().put ("sampleProp2" , new EntityProperty (Base64 .decode ("KXjuBNn9DesCmMcdVpamJw==" )));
1117+ dteJavaOld .getProperties ().put ("sampleProp3" , new EntityProperty (Base64 .decode ("wykVEni1rV+H6oNjoNml6A==" )));
1118+ dteJavaOld .getProperties ().put ("_ClientEncryptionMetadata1" , new EntityProperty ("{\" WrappedContentKey\" :{\" KeyId\" :\" key1\" ,\" EncryptedKey\" :\" 2F4rIuDmGPgEmhpvTtE7x6281BetKz80EsgRwGxTjL8rRt7Z7GrOgg==\" ,\" Algorithm\" :\" A256KW\" },\" EncryptionAgent\" :{\" Protocol\" :\" 1.0\" ,\" EncryptionAlgorithm\" :\" AES_CBC_256\" },\" ContentEncryptionIV\" :\" 8st/uXffG+6DxBhw4D1URw==\" }" ));
1119+ dteJavaOld .getProperties ().put ("_ClientEncryptionMetadata2" , new EntityProperty (Base64 .decode ("WznUoytxkvl9KhZ4mNlqkBvRTUHN/D5IgJmNl7kQBOtFBOSgZZrTfZXKH8GjmvKA" )));
1120+
1121+ testTable .execute (TableOperation .insert (dteJavaOld ));
1122+
1123+ TableEncryptionPolicy policy = new TableEncryptionPolicy (sampleKEK , null );
1124+ TableRequestOptions options = new TableRequestOptions ();
1125+ options .setEncryptionPolicy (policy );
1126+ options .setEncryptionResolver (new EncryptionResolver () {
1127+ public boolean encryptionResolver (String pk , String rk , String key ) {
1128+ return true ;
1129+ }
1130+ });
1131+
1132+ for (DynamicTableEntity dte : testTable .execute (TableQuery .from (DynamicTableEntity .class ), options , null ))
1133+ {
1134+ assertTrue ("String not properly decoded." , dte .getProperties ().get ("sampleProp" ).getValueAsString ().equals ("sampleValue" ));
1135+ assertTrue ("String not properly decoded." , dte .getProperties ().get ("sampleProp2" ).getValueAsString ().equals ("sampleValue" ));
1136+ assertTrue ("String not properly decoded." , dte .getProperties ().get ("sampleProp3" ).getValueAsString ().equals ("sampleValue" ));
1137+ assertEquals ("Incorrect number or properties" , dte .getProperties ().size (), 3 );
1138+ }
1139+ }
1140+ finally
1141+ {
1142+ if (testTable != null ) {
1143+ testTable .deleteIfExists ();
1144+ }
1145+ }
10751146 }
10761147
10771148 private ArrayList <String > listAllTables (CloudTableClient tableClient , String prefix , TableRequestOptions options ) throws StorageException
@@ -1096,6 +1167,4 @@ private static DynamicTableEntity generateRandomEntity(String pk) {
10961167 ent .setRowKey (UUID .randomUUID ().toString ());
10971168 return ent ;
10981169 }
1099- }
1100-
1101-
1170+ }
0 commit comments