国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

javax.crypto.Cipher 源碼學習筆記

余學文 / 1797人閱讀

摘要:源碼學習筆記該類是用來加密的引擎類,支持對稱和非對稱加密。函數創建對象操作其中方法是在中操作的方法,其他幾個都使用執行。狀態變化內部類內部類是用來解析中傳入的字符串的。查詢時,也會查詢別名是否等于。知其然知其所以然。

javax.crypto.Cipher 源碼學習筆記

該類是JCE用來加密的引擎類,支持對稱和非對稱加密。該類的介紹可以參考:[[譯]JCA參考指南(二):核心類和接口](https://xshandow.gitee.io/201...

最近看了下OpenJDK中的Cipher源碼,現在介紹一下Cipher的內部實現。

1.Cipher函數

創建Cipher對象:getInstance()

操作:init()、update()、doFinal()

GCM|CCM:updateAAD()

其中:getInstance()方法是在Cipher中操作的方法,其他幾個都使用spi.engin**()執行。

狀態變化:

2.內部類Transform

內部類Transform是用來解析getInstanse()中傳入的transform字符串的。

setModePadding(CipherSpi spi)中通過spi.engineSetMode(mode|pad)設置,反饋模式和補丁方案。

判斷Provider.service是否支持提供的mod和pad.

3.getInstanse()

getInstanse()傳入的轉換的格式如下:

“algorithm/mode/padding” or(標準名稱)

“algorithm”

只傳入transformation:

public static final Cipher getInstance(String transformation)
        throws NoSuchAlgorithmException, NoSuchPaddingException
{
    //獲取Transform列表,帶alg
    List transforms = getTransforms(transformation);
    List cipherServices = new ArrayList(transforms.size());
    
    for (Iterator t = transforms.iterator(); t.hasNext(); ) {
        Transform transform = (Transform)t.next();

        //transform = alg + sufix(/[mode] + /[padding])
        //有四種形式:mode和padding是可選的
        cipherServices.add(new ServiceId("Cipher", transform.transform));
    }
    //獲取支持Transform(alg+suffix)的List
    //所有的Provider全部遍歷一遍
    List services = GetInstance.getServices(cipherServices);
    // make sure there is at least one service from a signed provider
    // and that it can use the specified mode and padding
    Iterator t = services.iterator();
    Exception failure = null;
    while (t.hasNext()) {
        Service s = (Service)t.next();
        if (JceSecurity.canUseProvider(s.getProvider()) == false) {
            continue;
        }
        //返回 transforms.suffix和算法的后綴一樣的第一個Transform
        Transform tr = getTransform(s, transforms);
        if (tr == null) {
            // should never happen
            continue;
        }
        //是否支持
        int canuse = tr.supportsModePadding(s);
        if (canuse == S_NO) {
            // does not support mode or padding we need, ignore
            continue;
        }
        //找到第一個結束
        if (canuse == S_YES) {
            return new Cipher(null, s, t, transformation, transforms);
        } else { // S_MAYBE, try out if it works
            try {
                CipherSpi spi = (CipherSpi)s.newInstance(null);
                tr.setModePadding(spi);
                return new Cipher(spi, s, t, transformation, transforms);
            } catch (Exception e) {
                failure = e;
            }
        }
    }
    throw new NoSuchAlgorithmException
        ("Cannot find any provider supporting " + transformation, failure);
}

另一種同時傳入Provider:

 public static final Cipher getInstance(String transformation,Provider provider)
        throws NoSuchAlgorithmException, NoSuchPaddingException
{
    if (provider == null) {
        throw new IllegalArgumentException("Missing provider");
    }
    Exception failure = null;
    List transforms = getTransforms(transformation);
    boolean providerChecked = false;
    String paddingError = null;
    for (Iterator t = transforms.iterator(); t.hasNext();) {
        Transform tr = (Transform)t.next();
        //直接搜該provider是否支持
        Service s = provider.getService("Cipher", tr.transform);
        if (s == null) {
            continue;
        }
        if (providerChecked == false) {
            // for compatibility, first do the lookup and then verify
            // the provider. this makes the difference between a NSAE
            // and a SecurityException if the
            // provider does not support the algorithm.
            Exception ve = JceSecurity.getVerificationResult(provider);
            if (ve != null) {
                String msg = "JCE cannot authenticate the provider "
                    + provider.getName();
                throw new SecurityException(msg, ve);
            }
            providerChecked = true;
        }
        if (tr.supportsMode(s) == S_NO) {
            continue;
        }
        if (tr.supportsPadding(s) == S_NO) {
            paddingError = tr.pad;
            continue;
        }
        try {
            CipherSpi spi = (CipherSpi)s.newInstance(null);
            tr.setModePadding(spi);
            Cipher cipher = new Cipher(spi, transformation);
            cipher.provider = s.getProvider();
            cipher.initCryptoPermission();
            return cipher;
        } catch (Exception e) {
            failure = e;
        }
    }

    // throw NoSuchPaddingException if the problem is with padding
    if (failure instanceof NoSuchPaddingException) {
        throw (NoSuchPaddingException)failure;
    }
    if (paddingError != null) {
        throw new NoSuchPaddingException
            ("Padding not supported: " + paddingError);
    }
    throw new NoSuchAlgorithmException
            ("No such algorithm: " + transformation, failure);
}

第一個getInstance(),將transform轉換成內部Transform,遍歷所有的Provider,查詢到第一個支持transform的Service,然后new Cipher().

第二種getInstance(),將transform轉換成內部Transform,直接通過provider.getService("Cipher", tr.transform)查詢是否支持transform,然后new Cipher().

注意:

tr.transform是通過下面介紹的的函數獲得的。

查詢service時,也會查詢別名是否等于tr.transform。

4.List getTransforms(String transformation)
/**
 * 獲取Transform的List列表
 */
private static List getTransforms(String transformation)
        throws NoSuchAlgorithmException {
    String[] parts = tokenizeTransformation(transformation);

    String alg = parts[0];
    String mode = parts[1];
    String pad = parts[2];
    if ((mode != null) && (mode.length() == 0)) {
        mode = null;
    }
    if ((pad != null) && (pad.length() == 0)) {
        pad = null;
    }

    //Transform 僅有alg
    if ((mode == null) && (pad == null)) {
        // DES
        Transform tr = new Transform(alg, "", null, null);
        return Collections.singletonList(tr);
    } else { 
        // Transform = alg/mode/padding 的格式
        // if ((mode != null) && (pad != null)) {
        // DES/CBC/PKCS5Padding
        List list = new ArrayList(4);
        list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
        list.add(new Transform(alg, "/" + mode, null, pad));
        list.add(new Transform(alg, "http://" + pad, mode, null));
        list.add(new Transform(alg, "", mode, pad));
        return list;
    }
}
如果transform的格式時“algorithm/mode/padding”,會輸出4中形式的Transform,查詢支持某種就會返回。
4.ini()
public final void init(int opmode, Key key, SecureRandom random)
        throws InvalidKeyException
{
    initialized = false;
    checkOpmode(opmode);

    if (spi != null) {
        checkCryptoPerm(spi, key);
        spi.engineInit(opmode, key, random);
    } else {
        try {
            chooseProvider(I_KEY, opmode, key, null, null, random);
        } catch (InvalidAlgorithmParameterException e) {
            // should never occur
            throw new InvalidKeyException(e);
        }
    }

    initialized = true;
    this.opmode = opmode;
}

如上代碼,執行ini()、update()..等操作時,其實是執行spi.engin**()

如果使用的mod需要傳入IV,這使用,init(Mode,Key,IvParameterSpec)出入IV。

GCMParameterSpec的時候IV必須每次都不同。

Transform標準名稱

可以參考Java Cryptography Architecture Standard Algorithm Name Documentation for JDK 8

總結

看Cipher源碼的原因是因為,在看BC的時候看到支持的transform列表中支持的是RSA/OAEP的加密模式,但是JCE中要求的傳日格式是“algorithm/mode/padding” or(標準名稱)“algorithm”,因此就產生了以問。

BC: Cipher.RSA -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$NoPadding
  aliases: [RSA//RAW, RSA//NOPADDING]
  attributes: {SupportedKeyFormats=PKCS#8|X.509, SupportedKeyClasses=javax.crypto.interfaces.RSAPublicKey|javax.crypto.interfaces.RSAPrivateKey}

BC: Cipher.RSA/RAW -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$NoPadding

BC: Cipher.RSA/PKCS1 -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$PKCS1v1_5Padding
  aliases: [RSA//PKCS1PADDING]

BC: Cipher.RSA/1 -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$PKCS1v1_5Padding_PrivateOnly

BC: Cipher.RSA/2 -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$PKCS1v1_5Padding_PublicOnly

BC: Cipher.RSA/OAEP -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$OAEPPadding
  aliases: [RSA//OAEPPADDING]

BC: Cipher.RSA/ISO9796-1 -> org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi$ISO9796d1Padding
  aliases: [RSA//ISO9796-1PADDING]

可以看出RSA/OAEP的別名正事RSA//OAEPPADING,所以也能夠查到RSA//OAEPPADING對應的正是service中的RSA/OAEP。

知其然知其所以然。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76821.html

相關文章

  • 慕課網_《Java實現對稱加密》學習總結

    時間:2017年4月11日星期二說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學示例源碼:https://github.com/zccodere/s...個人學習源碼:https://github.com/zccodere/s... 第一章:對稱加密算法DES 1-1 JAVA對稱加密算法DES 加密密鑰=解密密鑰 對稱加密算法 初等 DES --3D...

    tomlingtm 評論0 收藏0
  • 慕課網_《Java實現非對稱加密》學習總結

    摘要:時間年月日星期三說明本文部分內容均來自慕課網。秘密密鑰,生成一個分組的秘密密鑰。 時間:2017年4月12日星期三說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學示例源碼:https://github.com/zccodere/s...個人學習源碼:https://github.com/zccodere/s... 第一章:概述 1-1 概述 非對稱...

    dailybird 評論0 收藏0
  • Java加密算法筆記--DES算法實現

    摘要:加密算法筆記算法實現在使用中發現,經過加密的字符串如果要進行傳輸,需要使用進行編碼,這樣能保證加密信息的完整性,確保將來解密成功。 Java加密算法筆記--DES算法實現 在使用中發現,經過加密的字符串如果要進行傳輸,需要使用Base64進行編碼,這樣能保證加密信息的完整性,確保將來解密成功。 import java.security.SecureRandom; import java...

    BlackFlagBin 評論0 收藏0
  • 原創:微信小程序java實現AES解密并獲取unionId

    摘要:來自微信小程序聯盟如果大家使用小程序的同時還在使用公眾號的話,可能會用到這種功能,由于公司業務需要,我們需要使用,具體使用方法,請參考微信開放平臺的說明,但是在微信小程序的文檔中只給出了部分語言實現的源碼,竟然沒有的,小程序的開發人員是有多 來自:微信小程序聯盟 如果大家使用小程序的同時還在使用公眾號的話,可能會用到unionId這種功能,由于公司業務需要,我們需要使用unionId,...

    jackzou 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<