RSA 數(shù)據(jù)加密及簽名

原理:

   將兩個(gè)大素?cái)?shù)相乘十分容易,但是想要對其乘積進(jìn)行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰。
RSA 正是這個(gè)原因, 生成的密鑰對其實(shí)也是可以互相替換的,A 作為公鑰, B 就可以作為私鑰解密, B作為公鑰,A 就可以作為私鑰解密。

但是生成的AB 長度差異較大。通常用短的作為公鑰,以減少加密的算法成本,相對而言解密的成本變高。

私鑰如果太小,敵人可以在 logn 的時(shí)間內(nèi)破解 畢竟窮舉就是 2^n

使用方式, 公鑰就是在外部傳播的密鑰串, 私鑰是所有人持有的。

加密傳輸時(shí),發(fā)送人用公鑰加密數(shù)據(jù),發(fā)送給所有人,所有人通過私鑰解密獲得數(shù)據(jù)。
簽名認(rèn)證時(shí),所有人用私鑰加密數(shù)據(jù),廣播告知,其他人用公鑰嘗試解密校驗(yàn),校驗(yàn)一致則密文未被篡改且是對應(yīng)所有人發(fā)布的。實(shí)際操作時(shí),通常對摘要信息進(jìn)行處理完成對應(yīng)的工作。 比如對發(fā)布的信息取 md5(SHA1 或SHA 256), 然后用私鑰對相應(yīng)的 md5 加密(生成簽名)。 其他人接受到后,先生成摘要,然后與解密后的字串對比 來判斷是否被篡改和一致性。
  1. 事實(shí)上Android apk 的簽名也是與此一致。
Android 的簽名信息主要保存在。 MANIFEST.MF、CERT.SF和CERT.RSA 中
流程是遍歷除了簽名文件意外的entry, 生成摘要(SHA1)。保存在 MANIFEST.MF
對MANIFEST.MF 進(jìn)行rsa 私鑰簽名 防止篡改 并記錄在CERT.SF中
CERT.RSA文件中保存了公鑰、所采用的加密算法等信息
因此框架中讀取公鑰的算法也是通過這個(gè)文件來獲取。
讀取代碼如下,
含義即 私鑰 信息協(xié)議是PSCS7  公鑰信息協(xié)議是 X509 簽名算法是SHA1
   Signature signature, X509Certificate publicKey, OutputStream out)
              throws IOException, GeneralSecurityException {
                  SignerInfo signerInfo = new SignerInfo(
                  new X500Name(publicKey.getIssuerX500Principal().getName()),
                  publicKey.getSerialNumber(),
                  AlgorithmId.get("SHA1"),
                  AlgorithmId.get("RSA"),
                  signature.sign());
 
              PKCS7 pkcs7 = new PKCS7(
             new AlgorithmId[] { AlgorithmId.get("SHA1") },
             new ContentInfo(ContentInfo.DATA_OID, null),
             new X509Certificate[] { publicKey },
             new SignerInfo[] { signerInfo });
  1. 編碼加密解密都是針對字節(jié)流,完成之后要對字節(jié)流編碼。通常的方式是。 Base64.encode(bytes, Base64.DEFAULT) 然后 new String(code , “UTF-8”);
    對應(yīng)的解碼時(shí)也要按照base 64 解碼

客戶端和服務(wù)端代碼案例:

生成密鑰對代碼

  /**
     * 生成密鑰對
     *
     * @return
     */
    public Map<String, byte[]> generateKeyBytes() {

        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator
                    .getInstance(KEY_ALGORITHM);
            keyPairGenerator.initialize(KEY_SIZE);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            Map<String, byte[]> keyMap = new HashMap<String, byte[]>();
            keyMap.put(PUBLIC_KEY, publicKey.getEncoded());
            keyMap.put(PRIVATE_KEY, privateKey.getEncoded());
            return keyMap;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

服務(wù)端簽名

/**
 * 還原私鑰
 *
 * @param keyBytes
 * @return
 */
public PrivateKey restorePrivateKey(byte[] keyBytes) {
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
            keyBytes);
    try {
        KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateKey = factory
                .generatePrivate(pkcs8EncodedKeySpec);
        return privateKey;
    } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * 簽名
 *
 * @param privateKey 私鑰
 * @param plain_text 明文
 * @return
 */
public byte[] sign(PrivateKey privateKey, String plain_text) {
    MessageDigest messageDigest;
    byte[] signed = null;
    try {
        messageDigest = MessageDigest.getInstance(ENCODE_ALGORITHM);
        messageDigest.update(plain_text.getBytes());
        byte[] outputDigest_sign = messageDigest.digest();
        //System.out.println("SHA-256加密后-----》" +bytesToHexString(outputDigest_sign));
        Signature Sign = Signature.getInstance(SIGNATURE_ALGORITHM);
        Sign.initSign(privateKey);
        Sign.update(outputDigest_sign);
        signed = Sign.sign();
        //  System.out.println("SHA256withRSA簽名后-----》" + bytesToHexString(signed));
    } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
        e.printStackTrace();
    }
    return signed;
}

public String base64Signed(PrivateKey privateKey, String plain_text) {
    return Base64.encodeBase64String(sign(privateKey, plain_text));
}

客戶端驗(yàn)證

/**
 * Generates a PublicKey instance from a string containing the
 * Base64-encoded public key.
 *
 * @param encodedPublicKey Base64-encoded public key
 * @throws IllegalArgumentException if encodedPublicKey is invalid
 */
static PublicKey generatePublicKey(String encodedPublicKey) {
    try {
        byte[] decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
        return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    } catch (InvalidKeySpecException e) {
        Log.e(TAG, "Invalid key specification.");
        throw new IllegalArgumentException(e);
    }
}

/**
 * Verifies that the signature from the server matches the computed
 * signature on the data.  Returns true if the data is correctly signed.
 *
 * @param publicKey  public key associated with the developer account
 * @param signedData signed data from server
 * @param signature  server signature
 * @return true if the data and signature match
 */
static boolean verify(PublicKey publicKey, String signedData, String signature) {
    MessageDigest messageDigest = null;
    try {
        messageDigest = MessageDigest.getInstance(ENCODE_ALGORITHM);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        Log.e(TAG, "digest generate failed");
        return false;
    }
    messageDigest.update(signedData.getBytes());
    byte[] digestBytes = messageDigest.digest();


    try {
        Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
        sig.initVerify(publicKey);
        sig.update(digestBytes);
        byte[] decodedSignature = Base64.decode(signature, Base64.DEFAULT);
        if (!sig.verify(decodedSignature)) {
            Log.e(TAG, "Signature verification failed.");
            return false;
        }
        return true;
    } catch (NoSuchAlgorithmException e) {
        Log.e(TAG, "NoSuchAlgorithmException.");
    } catch (InvalidKeyException e) {
        Log.e(TAG, "Invalid key specification.");
    } catch (SignatureException e) {
        Log.e(TAG, "Signature exception.");
    }
    return false;
}

Android. 獲取簽名

    /**
     * 獲取簽名公鑰
     *
     * @param mContext
     * @return
     */
    @Nullable
    public static String getSignInfo(Context mContext, String packageName) {
        if (TextUtils.isEmpty(packageName)) return "";
        String signCode = "";
        try {
            PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(
                    packageName, PackageManager.GET_SIGNATURES);
            Signature[] signs = packageInfo.signatures;
            Signature sign = signs[0];
//            String sha1 = signatureSHA1(signs);
            String sha256 = signatureSHA256(signs);
//            signCode = parseSignature(sign.toByteArray());
            signCode = sha256;
        } catch (Exception e) {
        }
        return signCode;
    }

    /**
     * SHA1
     */
    public static String signatureSHA1(Signature[] signatures) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            if (signatures != null) {
                for (Signature s : signatures)
                    digest.update(s.toByteArray());
            }
            return toHexString(digest.digest());
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 進(jìn)行轉(zhuǎn)換
     */
    public static String toHexString(byte[] bData) {
        StringBuilder sb = new StringBuilder(bData.length * 2);
        for (int i = 0; i < bData.length; i++) {
            sb.append(HEX_DIGITS[(bData[i] & 0xf0) >>> 4]);
            sb.append(HEX_DIGITS[bData[i] & 0x0f]);
        }
        return sb.toString();
    }

    /**
     * SHA256
     */
    public static String signatureSHA256(Signature[] signatures) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            if (signatures != null) {
                for (Signature s : signatures)
                    digest.update(s.toByteArray());
            }
            return toHexString(digest.digest());
        } catch (Exception e) {
            return "";
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容