Cipher.java 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //Copyright (C) 2014 by Yan Huang <yhuang@virginia.edu>
  2. package com.oblivm.backend.ot;
  3. import java.math.BigInteger;
  4. import java.nio.ByteBuffer;
  5. import java.security.MessageDigest;
  6. import com.oblivm.backend.gc.GCSignal;
  7. public final class Cipher {
  8. private static final int unitLength = 160; // SHA-1 has 160-bit output.
  9. private static final int bytesPerUnit = (unitLength - 1) / 8 + 1; // SHA-1
  10. // has
  11. // 20
  12. // bytes.
  13. private MessageDigest sha1;
  14. public Cipher() {
  15. try {
  16. sha1 = MessageDigest.getInstance("SHA-1");
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. System.exit(1);
  20. }
  21. }
  22. BigInteger a = BigInteger.ONE;
  23. public BigInteger encrypt(byte[] key, BigInteger msg, int msgLength) {
  24. assert (msgLength <= unitLength) : "Message longer than hash block width.";
  25. return msg.xor(getPaddingOfLength(key, msgLength));
  26. }
  27. public BigInteger decrypt(byte[] key, BigInteger cph, int cphLength) {
  28. assert (cphLength > unitLength) : "Ciphertext longer than hash block width.";
  29. return cph.xor(getPaddingOfLength(key, cphLength));
  30. }
  31. private BigInteger getPaddingOfLength(byte[] key, int padLength) {
  32. byte[] pad = new byte[(padLength - 1) / 8 + 1];
  33. byte[] tmp;
  34. int i;
  35. for (i = 0; i < (pad.length - 1) / bytesPerUnit; i++) {
  36. assert (i < 128) : "Padding is unexpectedly long.";
  37. sha1.update(key);
  38. sha1.update((byte) i);
  39. tmp = sha1.digest();
  40. System.arraycopy(tmp, 0, pad, i * bytesPerUnit, bytesPerUnit);
  41. }
  42. return new BigInteger(1, pad);
  43. }
  44. public BigInteger encrypt(int j, byte[] key, BigInteger msg, int msgLength) {
  45. return msg.xor(getPaddingOfLength(j, key, msgLength));
  46. }
  47. public BigInteger decrypt(int j, byte[] key, BigInteger cph, int cphLength) {
  48. return cph.xor(getPaddingOfLength(j, key, cphLength));
  49. }
  50. private BigInteger getPaddingOfLength(int j, byte[] key, int padLength) {
  51. sha1.update(ByteBuffer.allocate(4).putInt(j).array());
  52. sha1.update(key);
  53. byte[] pad = new byte[(padLength - 1) / 8 + 1];
  54. byte[] tmp;
  55. tmp = sha1.digest();
  56. int i;
  57. for (i = 0; i < (pad.length - 1) / bytesPerUnit; i++) {
  58. System.arraycopy(tmp, 0, pad, i * bytesPerUnit, bytesPerUnit);
  59. sha1.update(tmp);
  60. tmp = sha1.digest();
  61. }
  62. System.arraycopy(tmp, 0, pad, i * bytesPerUnit, pad.length - i * bytesPerUnit);
  63. return new BigInteger(1, pad);
  64. }
  65. public GCSignal enc(GCSignal key, GCSignal m, int k) {
  66. return getPadding(key, k).xor(m);
  67. }
  68. public GCSignal dec(GCSignal key, GCSignal c, int k) {
  69. return getPadding(key, k).xor(c);
  70. }
  71. private GCSignal getPadding(GCSignal key, int k) {
  72. sha1.update(key.bytes);
  73. sha1.update(ByteBuffer.allocate(4).putInt(k).array());
  74. GCSignal ret = GCSignal.newInstance(sha1.digest());
  75. return ret;
  76. }
  77. }