Skip to content

Commit

Permalink
Update the encryption scenario test to validate that the server can c…
Browse files Browse the repository at this point in the history
…orrectly decrypt the file (issue #575)

Rework Encryption helper to remove dependency on Bouncy Castle (fewer dependencies are better)
Removed "Microsoft-Internal" file, retargeted test to use unrestricted media file (issue #564)
  • Loading branch information
jcookems committed Dec 22, 2012
1 parent b49d5f3 commit be47bb5
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 182 deletions.
6 changes: 0 additions & 6 deletions microsoft-azure-api/pom.xml
Expand Up @@ -104,12 +104,6 @@
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.1</version> <version>3.1</version>
</dependency> </dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>


<build> <build>
Expand Down
Expand Up @@ -16,100 +16,50 @@
package com.microsoft.windowsazure.services.media; package com.microsoft.windowsazure.services.media;


import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key; import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.cert.CertificateException; import java.security.cert.Certificate;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Random;
import java.util.UUID;


import javax.crypto.BadPaddingException;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.CipherInputStream; import javax.crypto.CipherInputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;


import com.microsoft.windowsazure.services.core.storage.utils.Base64; import com.microsoft.windowsazure.services.core.storage.utils.Base64;


public class EncryptionHelper { class EncryptionHelper {

public static byte[] encryptSymmetricKey(String protectionKey, byte[] inputData) throws Exception {
public static byte[] createRandomVector(int numberOfBits) { Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
int numberOfBytes = numberOfBits / 8;
byte[] randomVector = new byte[numberOfBytes];
Random random = new Random();
random.nextBytes(randomVector);
return randomVector;
}

public static byte[] EncryptSymmetricKey(String protectionKey, byte[] inputData) throws Exception {

X509Certificate x509Certificate = createX509CertificateFromString(protectionKey);
return EncryptSymmetricKey(x509Certificate.getPublicKey(), inputData);
}

private static X509Certificate createX509CertificateFromString(String protectionKey) throws CertificateException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.decode(protectionKey)); byte[] protectionKeyBytes = Base64.decode(protectionKey);
X509Certificate x509cert = (X509Certificate) certificateFactory.generateCertificate(byteArrayInputStream); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(protectionKeyBytes);
return x509cert; Certificate certificate = certificateFactory.generateCertificate(byteArrayInputStream);

Key publicKey = certificate.getPublicKey();
}

public static byte[] EncryptSymmetricKey(Key publicKey, byte[] inputData) throws NoSuchAlgorithmException,
NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException,
BadPaddingException {
Cipher cipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");
SecureRandom secureRandom = new SecureRandom(); SecureRandom secureRandom = new SecureRandom();
cipher.init(Cipher.ENCRYPT_MODE, publicKey, secureRandom); cipher.init(Cipher.ENCRYPT_MODE, publicKey, secureRandom);
byte[] cipherText = cipher.doFinal(inputData); byte[] cipherText = cipher.doFinal(inputData);
return cipherText; return cipherText;
} }


public static String calculateChecksum(UUID uuid, byte[] aesKey) throws NoSuchAlgorithmException, public static String calculateContentKeyChecksum(String uuid, byte[] aesKey) throws Exception {
NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
InvalidKeyException {
SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey, "AES"); SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING", "BC");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encryptionResult = cipher.doFinal(uuid.toString().getBytes()); byte[] encryptionResult = cipher.doFinal(uuid.getBytes("UTF8"));
byte[] checksumByteArray = new byte[8]; byte[] checksumByteArray = new byte[8];
for (int i = 0; i < 8; i++) { System.arraycopy(encryptionResult, 0, checksumByteArray, 0, 8);
checksumByteArray[i] = encryptionResult[i];
}
String checksum = Base64.encode(checksumByteArray); String checksum = Base64.encode(checksumByteArray);
return checksum; return checksum;
} }


public static byte[] EncryptFile(InputStream inputStream, byte[] aesKey, byte[] initializationVector) public static InputStream encryptFile(InputStream inputStream, byte[] key, byte[] iv) throws Exception {
throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
InvalidAlgorithmParameterException, IOException { SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
// preparation IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
SecretKeySpec key = new SecretKeySpec(aesKey, "AES"); cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
IvParameterSpec ivParameterSpec = new IvParameterSpec(initializationVector);
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");

// encryption
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher); CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); return cipherInputStream;

int ch;
while ((ch = cipherInputStream.read()) >= 0) {
byteArrayOutputStream.write(ch);
}

byte[] cipherText = byteArrayOutputStream.toByteArray();
return cipherText;
} }

} }

0 comments on commit be47bb5

Please sign in to comment.