本文主要是介绍golang将pkcs1格式的公钥转换为pkcs8格式的公钥,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
在工作中遇到golang编写的sdk作为客户端,java语言编写程序作为服务器端的情况,需要使用go生成一个RSA公钥发送给服务器端,此公钥用于加密某些消息,使用的是RSAOAEP的加解密算法,该算法包含了两次哈希函数,能够防止重放攻击,个人建议两次哈希函数都采用sha256。具体互通方法我会在后续博客中更新。此文主要介绍将pkcs1格式的公钥转成pkcs8格式公钥的方法。
密钥格式
下表为常见的密码学术语:
Term | Definition |
---|---|
PKI | Public Key Cryptography. Public-key cryptography, or asymmetric cryptography, is any cryptographic system that uses pairs of keys: public keys which may be disseminated widely, and private keys which are known only to the owner. This accomplishes two functions: authentication, where the public key verifies that a holder of the paired private key sent the message, and encryption, where only the paired private key holder can decrypt the message encrypted with the public key. |
PKCS | In cryptography, PKCS stands for “Public Key Cryptography Standards”. These are a group of public-key cryptography standards devised and published by RSA Security Inc, starting in the early 1990s. The company published the standards to promote the use of the cryptography techniques to which they had patents, such as the RSA algorithm, the Schnorr signature algorithm and several others. Though not industry standards (because the company retained control over them), some of the standards in recent years have begun to move into the “standards-track” processes of relevant standards organizations such as the IETF and the PKIX working-group. |
RSA | RSA (Rivest-Shamir-Adleman) is one of the first public-key cryptosystems and is widely used for secure data transmission. In such a cryptosystem, the encryption key is public and it is different from the decryption key which is kept secret (private). In RSA, this asymmetry is based on the practical difficulty of the factorization of the product of two large prime numbers, the “factoring problem”. The acronym RSA is made of the initial letters of the surnames of Ron Rivest, Adi Shamir, and Leonard Adleman, who first publicly described the algorithm in 1978. Clifford Cocks, an English mathematician working for the British intelligence agency Government Communications Headquarters (GCHQ), had developed an equivalent system in 1973, but this was not declassified until 1997.A user of RSA creates and then publishes a public key based on two large prime numbers, along with an auxiliary value. The prime numbers must be kept secret. Anyone can use the public key to encrypt a message, but with currently published methods, and if the public key is large enough, only someone with knowledge of the prime numbers can decode the message feasibly. Breaking RSA encryption is known as the RSA problem. Whether it is as difficult as the factoring problem remains an open question. |
Private Key | A Private Key is a secret key, used in Asymmetric Encryption. It is mathematically equivalent to a Public Key, but is kept secret. This is one half of a matching key-pair. |
Public Key | A Public Key is a publicly distributed key, used in Asymmetric Encryption. It is mathematically equivalent to a Private Key, but is widely distributed. This is the other half of a matching key-pair. |
PKCS#1 | In cryptography, PKCS #1 is the first of a family of standards called Public-Key Cryptography Standards (PKCS), published by RSA Laboratories. It provides the basic definitions of and recommendations for implementing the RSA algorithm for public-key cryptography. It defines the mathematical properties of public and private keys, primitive operations for encryption and signatures, secure cryptographic schemes, and related ASN.1 syntax representations. |
PKCS#8 | In cryptography, PKCS #8 is a standard syntax for storing private key information. PKCS #8 is one of the family of standards called Public-Key Cryptography Standards (PKCS) created by RSA Laboratories. The latest version, 1.2, is available as RFC 5208. |
Base64 | Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. The term Base64 originates from a specific MIME content transfer encoding. Each base64 digit represents exactly 6 bits of data. Three 8-bit bytes (i.e., a total of 24 bits) can therefore be represented by four 6-bit base64 digits. |
DER | DER (Distinguished Encoding Rules) is a restricted variant of BER for producing unequivocal transfer syntax for data structures described by ASN.1. Like CER, DER encodings are valid BER encodings. DER is the same thing as BER with all but one sender’s options removed. DER is a subset of BER providing for exactly one way to encode an ASN.1 value. DER is intended for situations when a unique encoding is needed, such as in cryptography, and ensures that a data structure that needs to be digitally signed produces a unique serialized representation. DER can be considered a canonical form of BER. For example, in BER a Boolean value of true can be encoded as any of 255 non-zero byte values, while in DER there is one way to encode a boolean value of true. |
ASN.1 | Abstract Syntax Notation One (ASN.1) is an interface description language for defining data structures that can be serialized and deserialized in a standard, cross-platform way. It is broadly used in telecommunications and computer networking, and especially in cryptography. |
PEM | PEM is a de facto file format for storing and sending cryptography keys, certificates, and other data, based on a set of 1993 IETF standards defining “privacy-enhanced mail.” While the original standards were never broadly adopted, and were supplanted by PGP and S/MIME, the textual encoding they defined became very popular. The PEM format was eventually formalized by the IETF in RFC 7468.Many cryptography standards use ASN.1 to define their data structures, and Distinguished Encoding Rules (DER) to serialize those structures. Because DER produces binary output, it can be challenging to transmit the resulting files through systems, like electronic mail, that only support ASCII. The PEM format solves this problem by encoding the binary data using base64. PEM also defines a one-line header, consisting of “—–BEGIN “, a label, and “—–“, and a one-line footer, consisting of “—–END “, a label, and “—–“. The label determines the type of message encoded. Common labels include “CERTIFICATE”, “CERTIFICATE REQUEST”, and “PRIVATE KEY”. PEM data is commonly stored in files with a “.pem” suffix, a “.cer” or “.crt” suffix (for certificates), or a “.key” suffix (for public or private keys).[2] The label inside a PEM file represents the type of the data more accurately than the file suffix, since many different types of data can be saved in a “.pem” file. |
参考链接:https://www.jhanley.com/security-key-pairs-and-private-public-keys/
通俗来讲,PKCS#1和PKCS#8都是公钥密码学中的标准实现,由RSA公司(拥有RSA算法专利)制定标准,设计实施。两种标准之间并不互通,需要通过字符编码来进行相互转换。网上已经有很多的私钥PKCS#1标准与PKCS#8标准互转的库,但是公钥互转的库有点少,本文主要实现了由PKCS#1标准公钥转换为PKCS#8标准公钥的方法。
具体实现
/*
* convert the pkcs1 public key to pbkcs8
*/
var BIT_STRING_TAG int = 0x03
var SEQUENCE_TAG int = 0x30
var NO_UNUSED_BITS = []byte{0x00}
var RSA_ALGORITHM_IDENTIFIER_SEQUENCE = []byte {
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
}func CreateSubjectPublicKeyInfoEncoding(pkcs1PublicKeyEncoding []byte) []byte {subjectPublicKeyBitString := createDEREncoding(BIT_STRING_TAG, concat(NO_UNUSED_BITS, pkcs1PublicKeyEncoding))subjectPublicKeyInfoValue := concat(RSA_ALGORITHM_IDENTIFIER_SEQUENCE, subjectPublicKeyBitString)subjectPublicKeyInfoSequence := createDEREncoding(SEQUENCE_TAG, subjectPublicKeyInfoValue)return subjectPublicKeyInfoSequence
}func concat(bas ... []byte) []byte {var buf []bytefor i := 0; i < len(bas); i++ {buf = append(buf, bas[i] ...)}return buf
}func createDEREncoding(tag int, value []byte) []byte {if tag < 0 || tag >= 0xFF {return nil}lengthEncoding := createDERLengthEncoding(len(value))var derEncodingBuf []bytederEncodingBuf = append(derEncodingBuf, createDERLengthEncoding(tag) ...)derEncodingBuf = append(derEncodingBuf, lengthEncoding ...)derEncodingBuf = append(derEncodingBuf, value ...)return derEncodingBuf
}func createDERLengthEncoding(size int) (b2 []byte) {if size <= 0x7F {res := uint8(size)b2 = append(b2, res)return b2} else if size <= 0xFF {
//X86 little-endianb2 = append(b2, uint8(0x81))var b [2]byteb[0] = uint8(size)b[1] = uint8(size >> 8)b2 = append(b2, b[1])b2 = append(b2, b[0])return b2} else if size <= 0xFFFF {
//X86 little-endianb2 = append(b2, uint8(0x82))var b [4]byteb[0] = uint8(size)b[1] = uint8(size >> 8)b[2] = uint8(size >> 16)b[3] = uint8(size >> 24)b2 = append(b2, b[1])b2 = append(b2, b[0])if size >> 16 == 0 {return b2}b2 = append(b2, b[3])b2 = append(b2, b[2])return b2}return nil
}
参考链接
这篇关于golang将pkcs1格式的公钥转换为pkcs8格式的公钥的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!