2017-04-19 141 views
1

非對稱密鑰我想類似的功能規定Easy way to store/restore encryption key for decrypting string in java保存並加載從jPBC

但是我的情況是不同的。在上面的鏈接,他們正在使用javax.crypto.*但對我來說,我使用org.bouncycastle.crypto.*it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.generators.*

我想存儲主祕密密鑰,公鑰和私鑰在不同的文件,並從文件中檢索這些密鑰。怎麼做 ?

以下是我在此離開的代碼TODO s。工作代碼可在github上找到。

import it.unisa.dia.gas.crypto.circuit.BooleanCircuit; 
import it.unisa.dia.gas.crypto.circuit.BooleanCircuit.BooleanCircuitGate; 
import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.engines.GGHSW13KEMEngine; 
import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.generators.GGHSW13KeyPairGenerator; 
import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.generators.GGHSW13ParametersGenerator; 
import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.generators.GGHSW13SecretKeyGenerator; 
import it.unisa.dia.gas.crypto.jpbc.fe.abe.gghsw13.params.*; 
import it.unisa.dia.gas.crypto.kem.cipher.engines.KEMCipher; 
import it.unisa.dia.gas.crypto.kem.cipher.params.KEMCipherDecryptionParameters; 
import it.unisa.dia.gas.crypto.kem.cipher.params.KEMCipherEncryptionParameters; 
import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory; 
import it.unisa.dia.gas.plaf.jpbc.util.concurrent.ExecutorServiceUtils; 
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 
import org.bouncycastle.crypto.CipherParameters; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 

import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import java.security.GeneralSecurityException; 
import java.security.SecureRandom; 
import java.security.Security; 
import java.security.spec.AlgorithmParameterSpec; 
import java.util.ArrayList; 
import java.util.List; 

import static it.unisa.dia.gas.crypto.circuit.Gate.Type.*; 

public class Example { 
    protected KEMCipher kemCipher; 
    protected AlgorithmParameterSpec iv; 

    protected AsymmetricCipherKeyPair keyPair; 


    public Example() throws GeneralSecurityException { 
     this.kemCipher = new KEMCipher(
       Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"), 
       new GGHSW13KEMEngine() 
     ); 

     // build the initialization vector. This example is all zeros, but it 
     // could be any value or generated using a random number generator. 
     iv = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); 
    } 


    public AsymmetricCipherKeyPair setup(int n) { 
     GGHSW13KeyPairGenerator setup = new GGHSW13KeyPairGenerator(); 
     setup.init(new GGHSW13KeyPairGenerationParameters(
       new SecureRandom(), 
       new GGHSW13ParametersGenerator().init(
         PairingFactory.getPairing("params/mm/ctl13/toy.properties"), 
         n).generateParameters() 
     )); 

     return (keyPair = setup.generateKeyPair()); 
    } 


    public byte[] initEncryption(String assignment) { 
     try { 
      return kemCipher.init(
        true, 
        new KEMCipherEncryptionParameters(
          128, 
          new GGHSW13EncryptionParameters(
            (GGHSW13PublicKeyParameters) keyPair.getPublic(), 
            assignment 
          ) 
        ), 
        iv 
      ); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public byte[] encrypt(String message) { 
     try { 
      return kemCipher.doFinal(message.getBytes()); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 


    public CipherParameters keyGen(BooleanCircuit circuit) { 
     GGHSW13SecretKeyGenerator keyGen = new GGHSW13SecretKeyGenerator(); 
     keyGen.init(new GGHSW13SecretKeyGenerationParameters(
       ((GGHSW13PublicKeyParameters) keyPair.getPublic()), 
       ((GGHSW13MasterSecretKeyParameters) keyPair.getPrivate()), 
       circuit 
     )); 

     return keyGen.generateKey(); 
    } 

    public byte[] decrypt(CipherParameters secretKey, byte[] encapsulation, byte[] ciphertext) { 
     try { 
      kemCipher.init(
        false, 
        new KEMCipherDecryptionParameters(secretKey, encapsulation, 128), 
        iv 
      ); 
      return kemCipher.doFinal(ciphertext); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 



    public static void main(String[] args) { 
     Security.addProvider(new BouncyCastleProvider()); 

     try { 
      // Setup 
      int n = 4; 
      Example engine = new Example(); 
      engine.setup(n); 

      // TODO: Here I want to store (GGHSW13PublicKeyParameters) keyPair.getPublic() and 
      // (GGHSW13MasterSecretKeyParameters) keyPair.getPrivate() in files and later to retrieve from file 

      // Encrypt 
      String message = "Hello World!!!"; 
      byte[] encapsulation = engine.initEncryption("1101"); 
      byte[] ciphertext = engine.encrypt(message); 

      BooleanCircuitGate bcg1 = new BooleanCircuitGate(INPUT, 0, 1); 

      BooleanCircuitGate[] bcgs = new BooleanCircuitGate[]{ 
        new BooleanCircuitGate(INPUT, 0, 1), 
        new BooleanCircuitGate(INPUT, 1, 1), 
        new BooleanCircuitGate(INPUT, 2, 1), 
        new BooleanCircuitGate(INPUT, 3, 1), 

        new BooleanCircuitGate(AND, 4, 2, new int[]{0, 1}), 
        new BooleanCircuitGate(OR, 5, 2, new int[]{2, 3}), 

        new BooleanCircuitGate(AND, 6, 3, new int[]{4, 5}), 
      }; 

      List<BooleanCircuitGate> bcgList = new ArrayList<BooleanCircuitGate>(); 

      bcgList.add(bcg1); 
      bcgList.add(new BooleanCircuitGate(INPUT, 1, 1)); 
      bcgList.add(new BooleanCircuitGate(INPUT, 2, 1)); 
      bcgList.add(new BooleanCircuitGate(INPUT, 3, 1)); 
      bcgList.add(new BooleanCircuitGate(AND, 4, 2, new int[]{0, 1})); 
      bcgList.add(new BooleanCircuitGate(OR, 5, 2, new int[]{2, 3})); 
      bcgList.add(new BooleanCircuitGate(AND, 6, 3, new int[]{4, 5})); 

      // Decrypt 
      int q = 3; 
      BooleanCircuit circuit = new BooleanCircuit(n, q, 3, bcgList.toArray(new BooleanCircuitGate[bcgList.size()])); 

      GGHSW13SecretKeyParameters secretKey = (GGHSW13SecretKeyParameters) engine.keyGen(circuit); 

      // TODO: Want to store secretKey in file and later to retrieve from file 

      byte[] plaintext = engine.decrypt(secretKey, encapsulation, ciphertext); 

      System.out.println(new String(plaintext)); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      ExecutorServiceUtils.shutdown(); 
     } 
    } 

} 
+0

所以你有問題嗎? –

+0

@ScaryWombat我想將主密鑰,公鑰和私鑰存儲在不同的文件中,並從文件中檢索這些密鑰。 – Junaid

+0

所以你想知道如何從文件中讀取數據? –

回答

2

生成主密鑰和公共參數後,應該存儲它們,以便以後可以實際使用它們。 jPBC不會爲您提供存儲這些密鑰的方法。另外,由於密鑰繼承自org.bouncycastle.crypto.params.AsymmetricKeyParameter,因此不能使用Java的序列化,因爲AsymmetricKeyParameter不實現Serializable接口。它doesn't沒有工作。

您將需要自己實現序列化。首先,你必須考慮你想要序列化的關鍵字裏面的對象是什麼類型的。在GGHSW13MasterSecretKeyParameters類的情況下,這是ElementintPairing

首先,您必須考慮是否要將Pairing包含在序列化的密鑰中。如果你這樣做,你必須在開始時寫入它,以便能夠稍後用於反序列化Element

如果我們假設一個Pairing實例是常量或始終由外部代碼提供,則序列化非常容易。你應該在前面寫一個格式版本,這樣你就可以在不丟掉所有以前序列化的密鑰的情況下改變你的格式。由於2年前遇到的錯誤,編寫元素更加棘手。基本的想法是,你寫出元素的字節長度和元素的內容。

public void serialize(GGHSW13MasterSecretKeyParameters msk, OutputStream out) throws IOException { 
    DataOutputStream dOut = new DataOutputStream(out); 

    dOut.writeInt(1); // version of the serialized format 
    dOut.writeInt(msk.getParameters().getN()); 

    serialize(msk.getAlpha(), dOut, msk.getParameters().getPairing()); 
} 

public void serialize(Element elem, DataOutputStream dOut, Pairing pairing) throws IOException { 
    dOut.writeBoolean(elem == null); 
    if (elem == null) { 
     return; 
    } 

    dOut.writeInt(pairing.getFieldIndex(elem.getField())); 
    byte[] bytes = elem.toBytes(); 
    dOut.writeInt(bytes.length); 
    dOut.write(bytes); 

    // this is a workaround because it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement does not serialize the infFlag 
    dOut.writeBoolean(elem instanceof CurveElement && elem.isZero()); 
    if (elem instanceof CurveElement && elem.isZero()) { 
     throw new IOException("Infinite element detected. They should not happen."); 
    } 
} 

OutputStream可以像FileOutputSteamByteArrayOutputStream

反序列化同樣簡單,但您需要明確提供Pairing,並且您需要確保始終按照您的要求讀取正確的字節數。通過寫入數據前面的int長度可知您請求的字節數。如果您不檢查該長度是否合理,則可能會引入安全問題,如拒絕服務漏洞或遠程代碼執行。

public GGHSW13MasterSecretKeyParameters deserialize(InputStream in, Pairing pairing) throws IOException { 
    DataInputStream dIn = new DataInputStream(in); 

    int version = dIn.readInt(); 
    if (version != 1) { 
     throw new RuntimeException("Unknown key format version: " + version); 
    } 

    int n = dIn.getInt(); 
    Element alpha = deserialize(dIn, pairing); 

    return new GGHSW13MasterSecretKeyParameters(
      new GGHSW13Parameters(pairing, n), 
      alpha 
    ); 
} 

public Element deserialize(DataInputStream dIn, Pairing pairing) throws IOException { 
    if (dIn.readBoolean()) { 
     return null; 
    } 

    int fieldIndex = dIn.readInt(); // TODO: check if this is in a sensible range 
    int length = dIn.readInt(); // TODO: check if this is in a sensible range 
    byte[] bytes = new byte[length]; 
    dIn.readFully(bytes); // throws an exception if there is a premature EOF 
    Element e = pairing.getFieldAt(fieldIndex).newElementFromBytes(bytes); 

    // this is a workaround because it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement does not serialize the infFlag 
    boolean instOfCurveElementAndInf = dIn.readBoolean(); 
    if (instOfCurveElementAndInf) { 
     //e.setToZero(); // according to the code this simply sets the infFlag to 1 
     throw new IOException("The point is infinite. This shouldn't happen."); 
    } 
    return e; 
} 

這是一個很小的二進制序列化。還有其他一些可能性,例如將所有組件編碼爲字符串並使用JSON。

+0

此代碼未經測試。如果您看到錯別字,請修改代碼或發表評論。 –

+0

明亮的解決方案,具有良好的描述。到目前爲止,我可以存儲和加載*主密鑰*和*公鑰*。你可以在這裏找到https://github.com/junaidbinsarfraz/ABE。現在可以請你幫我存儲和加載*密鑰*,因爲這涉及'BooleanCricuit'和'BooleanCricuit'涉及'AND','OR','NAND'和'INPUT''類型? – Junaid

+0

相同的技術將適用,但你必須遍歷電路遞歸可能存儲自己的引用。無論如何,這個問題已經超出了範圍。 –