• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Golang hkdf.New函数代码示例

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本文整理汇总了Golang中golang.org/x/crypto/hkdf.New函数的典型用法代码示例。如果您正苦于以下问题:Golang New函数的具体用法?Golang New怎么用?Golang New使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。



在下文中一共展示了New函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。

示例1: expandKey

// expandKey uses HKDF on SHA256 to create 256 bit random keys
// from cryptographically secure masterkey and salt.
func expandKey(masterkey []byte, nonsecretsalt []byte, count int) (keys [][]byte, err error) {

	hkdf := hkdf.New(sha256.New, masterkey, nonsecretsalt, []byte("Why not mix it up?"))

	// Generate keys
	keys = make([][]byte, count)
	for i := 0; i < count; i++ {
		keys[i] = make([]byte, 32)
		n, err := io.ReadFull(hkdf, keys[i])
		if err == nil && n != 32 {
			err = fmt.Errorf("expandKey: HKDF did not return 32 byte key. Len: %d\n", len(keys[i]))
		}
		if err != nil {
			return nil, err
		}
	}

	// Check for obvious leakage or non-randomness
	for i := 0; i < count; i++ {
		if bytes.Contains(keys[i], masterkey) {
			err = fmt.Errorf("expandKey: HKDF failed")
			return nil, err
		}
		for j := 0; j < i; j++ {
			if bytes.Equal(keys[i], keys[j]) {
				err = fmt.Errorf("expandKey: HKDF failed")
				return nil, err
			}
		}
	}

	return keys, nil
}
开发者ID:chrisroseatcat,项目名称:secure,代码行数:35,代码来源:secure.go


示例2: initClientTunnel

// Initializes a stream into an encrypted tunnel link.
func (c *Connection) initClientTunnel(strm *stream.Stream, remote uint64, id uint64, key []byte, deadline time.Time) (*link.Link, error) {
	// Set a socket deadline for finishing the handshake
	strm.Sock().SetDeadline(deadline)
	defer strm.Sock().SetDeadline(time.Time{})

	// Send the unencrypted tunnel id to associate with the remote tunnel
	init := &initPacket{ConnId: remote, TunId: id}
	if err := strm.Send(init); err != nil {
		return nil, err
	}
	// Create the encrypted link and authorize it
	hasher := func() hash.Hash { return config.HkdfHash.New() }
	hkdf := hkdf.New(hasher, key, config.HkdfSalt, config.HkdfInfo)
	conn := link.New(strm, hkdf, false)

	// Send and retrieve an authorization to verify both directions
	auth := &proto.Message{
		Head: proto.Header{
			Meta: &authPacket{Id: id},
		},
	}
	if err := conn.SendDirect(auth); err != nil {
		return nil, err
	}
	if msg, err := conn.RecvDirect(); err != nil {
		return nil, err
	} else if auth, ok := msg.Head.Meta.(*authPacket); !ok || auth.Id != id {
		return nil, errors.New("protocol violation")
	}
	conn.Start(config.IrisTunnelBuffer)

	// Return the initialized link
	return conn, nil
}
开发者ID:ibmendoza,项目名称:iris,代码行数:35,代码来源:tunnel.go


示例3: makeCipher

// Extracts a usable sized symmetric key and IV for the stream cipher from the huge master key, and
// creates a CTR stream cipher.
func (s *Session) makeCipher() (cipher.Stream, error) {
	// Create the key derivation function
	hasher := func() hash.Hash { return s.hash.New() }
	hkdf := hkdf.New(hasher, s.secret.Bytes(), hkdfSalt, hkdfInfo)

	// Extract the symmetric key
	key := make([]byte, s.keybits/8)
	n, err := io.ReadFull(hkdf, key)
	if n != len(key) || err != nil {
		return nil, err
	}
	// Create the block cipher
	block, err := s.crypter(key)
	if err != nil {
		return nil, err
	}
	// Extract the IV for the counter mode
	iv := make([]byte, block.BlockSize())
	n, err = io.ReadFull(hkdf, iv)
	if n != len(iv) || err != nil {
		return nil, err
	}
	// Create the stream cipher
	return cipher.NewCTR(block, iv), nil
}
开发者ID:ibmendoza,项目名称:project-iris,代码行数:27,代码来源:sts.go


示例4: split

// split is the final wrap-up act to be executed at the end of a succesful
// three act handshake. This function creates to internal cipherState
// instances: one which is used to encrypt messages from the initiator to the
// responder, and another which is used to encrypt message for the opposite
// direction.
func (b *BrontideMachine) split() {
	var (
		empty   []byte
		sendKey [32]byte
		recvKey [32]byte
	)

	h := hkdf.New(sha256.New, b.chainingKey[:], empty, empty)

	// If we're the initiator the the frist 32 bytes are used to encrypt
	// our messages and the second 32-bytes to decrypt their messages. For
	// the responder the opposite is true.
	if b.initiator {
		h.Read(sendKey[:])
		b.sendCipher = cipherState{}
		b.sendCipher.InitializeKey(sendKey)

		h.Read(recvKey[:])
		b.recvCipher = cipherState{}
		b.recvCipher.InitializeKey(recvKey)
	} else {
		h.Read(recvKey[:])
		b.recvCipher = cipherState{}
		b.recvCipher.InitializeKey(recvKey)

		h.Read(sendKey[:])
		b.sendCipher = cipherState{}
		b.sendCipher.InitializeKey(sendKey)
	}
}
开发者ID:lightningnetwork,项目名称:lnd,代码行数:35,代码来源:noise.go


示例5: Derive

// Derive uses HKDF with HMAC-SHA256 to derive key bytes in its material
// parameter.
func (d *Deriver) Derive(salt, context, material []byte) error {
	f := hkdf.New(sha256.New, d.secret, salt, context)
	if _, err := f.Read(material); err != nil {
		return err
	}

	return nil
}
开发者ID:tmroeder,项目名称:cloudproxy,代码行数:10,代码来源:keys.go


示例6: eciesEncrypt

func eciesEncrypt(rand io.Reader, pub *ecdsa.PublicKey, s1, s2 []byte, plain []byte) ([]byte, error) {
	params := pub.Curve

	// Select an ephemeral elliptic curve key pair associated with
	// elliptic curve domain parameters params
	priv, Rx, Ry, err := elliptic.GenerateKey(pub.Curve, rand)
	//fmt.Printf("Rx %s\n", utils.EncodeBase64(Rx.Bytes()))
	//fmt.Printf("Ry %s\n", utils.EncodeBase64(Ry.Bytes()))

	// Convert R=(Rx,Ry) to an octed string R bar
	// This is uncompressed
	Rb := elliptic.Marshal(pub.Curve, Rx, Ry)

	// Derive a shared secret field element z from the ephemeral secret key k
	// and convert z to an octet string Z
	z, _ := params.ScalarMult(pub.X, pub.Y, priv)
	Z := z.Bytes()
	//fmt.Printf("Z %s\n", utils.EncodeBase64(Z))

	// generate keying data K of length ecnKeyLen + macKeyLen octects from Z
	// ans s1
	kE := make([]byte, 32)
	kM := make([]byte, 32)
	hkdf := hkdf.New(primitives.GetDefaultHash(), Z, s1, nil)
	_, err = hkdf.Read(kE)
	if err != nil {
		return nil, err
	}
	_, err = hkdf.Read(kM)
	if err != nil {
		return nil, err
	}

	// Use the encryption operation of the symmetric encryption scheme
	// to encrypt m under EK as ciphertext EM
	EM, err := aesEncrypt(kE, plain)

	// Use the tagging operation of the MAC scheme to compute
	// the tag D on EM || s2
	mac := hmac.New(primitives.GetDefaultHash(), kM)
	mac.Write(EM)
	if len(s2) > 0 {
		mac.Write(s2)
	}
	D := mac.Sum(nil)

	// Output R,EM,D
	ciphertext := make([]byte, len(Rb)+len(EM)+len(D))
	//fmt.Printf("Rb %s\n", utils.EncodeBase64(Rb))
	//fmt.Printf("EM %s\n", utils.EncodeBase64(EM))
	//fmt.Printf("D %s\n", utils.EncodeBase64(D))
	copy(ciphertext, Rb)
	copy(ciphertext[len(Rb):], EM)
	copy(ciphertext[len(Rb)+len(EM):], D)

	return ciphertext, nil
}
开发者ID:RJAugust,项目名称:fabric,代码行数:57,代码来源:engine.go


示例7: calculateSignatureSecret

func calculateSignatureSecret(secret []byte) ([]byte, error) {
	signatureSecretHkdf := hkdf.New(sha256.New, []byte(secret), nil, []byte(HKDF_INFO_SIGNING))

	signatureSecret := make([]byte, sha256.Size)
	if _, err := io.ReadFull(signatureSecretHkdf, signatureSecret); err != nil {
		return nil, err
	}

	return signatureSecret, nil
}
开发者ID:mozilla-services,项目名称:go-syncstorage,代码行数:10,代码来源:token.go


示例8: newSession

// Creates a new, double link session for authenticated data transfer. The
// initiator is used to decide the key derivation order for the channels.
func newSession(conn *stream.Stream, secret []byte, server bool) *Session {
	// Create the key derivation function
	hasher := func() hash.Hash { return config.HkdfHash.New() }
	hkdf := hkdf.New(hasher, secret, config.HkdfSalt, config.HkdfInfo)

	// Create the encrypted control link
	return &Session{
		kdf:      hkdf,
		CtrlLink: link.New(conn, hkdf, server),
	}
}
开发者ID:ibmendoza,项目名称:iris,代码行数:13,代码来源:session.go


示例9: initServerTunnel

// Initializes a stream into an encrypted tunnel link.
func (o *Overlay) initServerTunnel(strm *stream.Stream) error {
	// Set a socket deadline for finishing the handshake
	strm.Sock().SetDeadline(time.Now().Add(config.IrisTunnelInitTimeout))
	defer strm.Sock().SetDeadline(time.Time{})

	// Fetch the unencrypted client initiator
	init := new(initPacket)
	if err := strm.Recv(init); err != nil {
		return err
	}
	o.lock.RLock()
	c, ok := o.conns[init.ConnId]
	o.lock.RUnlock()
	if !ok {
		return errors.New("connection not found")
	}
	c.tunLock.RLock()
	tun, ok := c.tunLive[init.TunId]
	c.tunLock.RUnlock()
	if !ok {
		return errors.New("tunnel not found")
	}
	// Create the encrypted link
	hasher := func() hash.Hash { return config.HkdfHash.New() }
	hkdf := hkdf.New(hasher, tun.secret, config.HkdfSalt, config.HkdfInfo)
	conn := link.New(strm, hkdf, true)

	// Send and retrieve an authorization to verify both directions
	auth := &proto.Message{
		Head: proto.Header{
			Meta: &authPacket{Id: tun.id},
		},
	}
	if err := conn.SendDirect(auth); err != nil {
		return err
	}
	if msg, err := conn.RecvDirect(); err != nil {
		return err
	} else if auth, ok := msg.Head.Meta.(*authPacket); !ok || auth.Id != tun.id {
		return errors.New("protocol violation")
	}
	conn.Start(config.IrisTunnelBuffer)

	// Send back the initialized link to the pending tunnel
	select {
	case tun.initDone <- conn:
		// Connection handled by initiator
		return nil
	case <-tun.initStop:
		// Initiator timed out or terminated, close
		conn.Close()
		return nil // No error, since tunnel was handled, albeit not as expected
	}
}
开发者ID:ibmendoza,项目名称:iris,代码行数:55,代码来源:tunnel.go


示例10: generateDerivedSecret

func generateDerivedSecret(secret []byte, salt string, encodedTokenSecret string) (string, error) {
	derivedHkdf := hkdf.New(sha256.New, []byte(secret), []byte(salt), []byte(HKDF_INFO_DERIVE+encodedTokenSecret))

	derivedSecret := make([]byte, sha256.Size)
	_, err := io.ReadFull(derivedHkdf, derivedSecret)
	if err != nil {
		return "", err
	}

	return base64.URLEncoding.EncodeToString(derivedSecret), nil
}
开发者ID:mozilla-services,项目名称:go-syncstorage,代码行数:11,代码来源:token.go


示例11: Kdf

// Kdf extracts and expands KEY_SEED via HKDF-SHA256 and returns `okm_len` bytes
// of key material.
func Kdf(keySeed []byte, okmLen int) []byte {
	kdf := hkdf.New(sha256.New, keySeed, tKey, mExpand)
	okm := make([]byte, okmLen)
	n, err := io.ReadFull(kdf, okm)
	if err != nil {
		panic(fmt.Sprintf("BUG: Failed HKDF: %s", err.Error()))
	} else if n != len(okm) {
		panic(fmt.Sprintf("BUG: Got truncated HKDF output: %d", n))
	}

	return okm
}
开发者ID:manawenuz,项目名称:obfs4,代码行数:14,代码来源:ntor.go


示例12: Sha512

// Sha512 returns a 256-bit key
func Sha512(master, salt, info []byte) ([32]byte, error) {
	hash := sha512.New
	hkdf := hkdf.New(hash, master, salt, info)

	key := make([]byte, 32) // 256 bit
	_, err := io.ReadFull(hkdf, key)

	var result [32]byte
	copy(result[:], key)

	return result, err
}
开发者ID:smitterson,项目名称:hc,代码行数:13,代码来源:hkdf.go


示例13: DeriveSecrets

// DeriveSecrets derives the requested number of bytes using HKDF, given
// the inputKeyMaterial, salt and the info
func DeriveSecrets(inputKeyMaterial, salt, info []byte, size int) ([]byte, error) {
	hkdf := hkdf.New(sha256.New, inputKeyMaterial, salt, info)

	secrets := make([]byte, size)
	n, err := io.ReadFull(hkdf, secrets)
	if err != nil {
		return nil, err
	}
	if n != size {
		return nil, err
	}
	return secrets, nil
}
开发者ID:mutantmonkey,项目名称:textsecure,代码行数:15,代码来源:ratchet.go


示例14: Read

// XXX TODO: return err if init() or Reset() has not been called
func (skgen *SecretKeyGen) Read(p []byte) (n int, err error) {
	prng := make([]byte, 256)
	n, err = io.ReadFull(rand.Reader, prng)
	if err != nil {
		//fmt.Fprintf(os.Stderr, "POUET POUET PROUT Error")
		//fmt.Println(err)
		return n, err
	}

	my_hkdf := hkdf.New(skgen.hash, skgen.input_pbkdf, prng, skgen.info_hkdf)
	n, err = io.ReadFull(my_hkdf, p)
	return n, err
}
开发者ID:gitter-badger,项目名称:ac,代码行数:14,代码来源:keygen.go


示例15: DeriveKey

// DeriveKey is used to derive the encryption key that should be used depending
// on the policy. If derivation is disabled the raw key is used and no context
// is required, otherwise the KDF mode is used with the context to derive the
// proper key.
func (p *policy) DeriveKey(context []byte, ver int) ([]byte, error) {
	if !p.Type.DerivationSupported() {
		return nil, errutil.UserError{Err: fmt.Sprintf("derivation not supported for key type %v", p.Type)}
	}

	if p.Keys == nil || p.LatestVersion == 0 {
		return nil, errutil.InternalError{Err: "unable to access the key; no key versions found"}
	}

	if ver <= 0 || ver > p.LatestVersion {
		return nil, errutil.UserError{Err: "invalid key version"}
	}

	// Fast-path non-derived keys
	if !p.Derived {
		return p.Keys[ver].AESKey, nil
	}

	// Ensure a context is provided
	if len(context) == 0 {
		return nil, errutil.UserError{Err: "missing 'context' for key deriviation. The key was created using a derived key, which means additional, per-request information must be included in order to encrypt or decrypt information"}
	}

	switch p.KDF {
	case kdf_hmac_sha256_counter:
		prf := kdf.HMACSHA256PRF
		prfLen := kdf.HMACSHA256PRFLen
		return kdf.CounterMode(prf, prfLen, p.Keys[ver].AESKey, context, 256)
	case kdf_hkdf_sha256:
		reader := hkdf.New(sha256.New, p.Keys[ver].AESKey, nil, context)
		derBytes := bytes.NewBuffer(nil)
		derBytes.Grow(32)
		limReader := &io.LimitedReader{
			R: reader,
			N: 32,
		}
		n, err := derBytes.ReadFrom(limReader)
		if err != nil {
			return nil, errutil.InternalError{Err: fmt.Sprintf("error reading returned derived bytes: %v", err)}
		}
		if n != 32 {
			return nil, errutil.InternalError{Err: fmt.Sprintf("unable to read enough derived bytes, needed 32, got %d", n)}
		}
		return derBytes.Bytes(), nil
	default:
		return nil, errutil.InternalError{Err: "unsupported key derivation mode"}
	}
}
开发者ID:chrishoffman,项目名称:vault,代码行数:52,代码来源:policy.go


示例16: OpenSession

// First argument is the algorithm used. "plain" (AlgoPlain) and
// "dh-ietf1024-sha256-aes128-cbc-pkcs7" (AlgoDH) are supported.
//
// The dbus api has the caller supply their DH public key and returns
// the other side's public key, but this implementation generates a
// new keypair, does the exchange, derives the encryption key, and then
// stores it in the returned Session.
func (s Service) OpenSession(algo string, args ...interface{}) (Session, error) {
	// spec: OpenSession(IN String algorithm, IN Variant input, OUT Variant output, OUT ObjectPath result);
	var ret Session
	conn, err := dbus.SessionBus()
	if err != nil {
		return ret, err
	}
	switch algo {
	case AlgoPlain:
		var discard dbus.Variant
		var sessionPath dbus.ObjectPath
		err = s.Call(_ServiceOpenSession, 0, algo, dbus.MakeVariant("")).Store(&discard, &sessionPath)
		if err != nil {
			return ret, err
		}
		ret = Session{conn.Object(ServiceName, sessionPath), algo, nil}
	case AlgoDH:
		// see http://standards.freedesktop.org/secret-service/ch07s03.html
		var sessionPath dbus.ObjectPath
		var srvReply dbus.Variant
		var srvPub []byte
		symKey := make([]byte, aes.BlockSize)
		grp, err := dhkx.GetGroup(2)
		if err != nil {
			return ret, err
		}
		privKey, err := grp.GeneratePrivateKey(rand.Reader)
		if err != nil {
			return ret, err
		}
		err = s.Call(_ServiceOpenSession, 0, algo, dbus.MakeVariant(privKey.Bytes())).Store(&srvReply, &sessionPath)
		if err != nil {
			return ret, err
		}
		srvPub = srvReply.Value().([]byte)
		sharedKey, err := grp.ComputeKey(dhkx.NewPublicKey(srvPub), privKey)
		if err != nil {
			return ret, err
		}
		_, err = io.ReadFull(hkdf.New(sha256.New, sharedKey.Bytes(), nil, nil), symKey)
		ret = Session{conn.Object(ServiceName, sessionPath), algo, symKey}
	default:
		err = InvalidAlgorithm
	}
	return ret, err
}
开发者ID:hdonnay,项目名称:secretservice,代码行数:53,代码来源:concrete.go


示例17: mixKey

// mixKey is implements a basic HKDF-based key rachet. This method is called
// with the result of each DH output generated during the handshake process.
// The first 32 bytes extract from the HKDF reader is the next chaining key,
// then latter 32 bytes become the temp secret key using within any future AEAD
// operations until another DH operation is performed.
func (s *symmetricState) mixKey(input []byte) {
	var info []byte

	secret := input
	salt := s.chainingKey
	h := hkdf.New(sha256.New, secret, salt[:], info)

	// hkdf(input, ck, zero)
	// |
	// | \
	// |  \
	// ck  k
	h.Read(s.chainingKey[:])
	h.Read(s.tempKey[:])

	// cipher.k = temp_key
	s.InitializeKey(s.tempKey)
}
开发者ID:lightningnetwork,项目名称:lnd,代码行数:23,代码来源:noise.go


示例18: deriveElkremRoot

// deriveElkremRoot derives an elkrem root unique to a channel given the
// private key for our public key in the 2-of-2 multi-sig, and the remote
// node's multi-sig public key. The root is derived using the HKDF[1][2]
// instantiated with sha-256. The secret data used is our multi-sig private
// key, with the salt being the remote node's public key.
//
// [1]: https://eprint.iacr.org/2010/264.pdf
// [2]: https://tools.ietf.org/html/rfc5869
func deriveElkremRoot(elkremDerivationRoot *btcec.PrivateKey,
	localMultiSigKey *btcec.PublicKey,
	remoteMultiSigKey *btcec.PublicKey) wire.ShaHash {

	secret := elkremDerivationRoot.Serialize()
	salt := localMultiSigKey.SerializeCompressed()
	info := remoteMultiSigKey.SerializeCompressed()

	rootReader := hkdf.New(sha256.New, secret, salt, info)

	// It's safe to ignore the error her as we know for sure that we won't
	// be draining the HKDF past its available entropy horizon.
	// TODO(roasbeef): revisit...
	var elkremRoot wire.ShaHash
	rootReader.Read(elkremRoot[:])

	return elkremRoot
}
开发者ID:lightningnetwork,项目名称:lnd,代码行数:26,代码来源:script_utils.go


示例19: Example_usage

// Usage example that expands one master key into three other cryptographically
// secure keys.
func Example_usage() {
	// Underlying hash function to use
	hash := sha256.New

	// Cryptographically secure master key.
	master := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this.

	// Non secret salt, optional (can be nil)
	// Recommended: hash-length sized random
	salt := make([]byte, hash().Size())
	n, err := io.ReadFull(rand.Reader, salt)
	if n != len(salt) || err != nil {
		fmt.Println("error:", err)
		return
	}

	// Non secret context specific info, optional (can be nil).
	// Note, independent from the master key.
	info := []byte{0x03, 0x14, 0x15, 0x92, 0x65}

	// Create the key derivation function
	hkdf := hkdf.New(hash, master, salt, info)

	// Generate the required keys
	keys := make([][]byte, 3)
	for i := 0; i < len(keys); i++ {
		keys[i] = make([]byte, 24)
		n, err := io.ReadFull(hkdf, keys[i])
		if n != len(keys[i]) || err != nil {
			fmt.Println("error:", err)
			return
		}
	}

	// Keys should contain 192 bit random keys
	for i := 1; i <= len(keys); i++ {
		fmt.Printf("Key #%d: %v\n", i, !bytes.Equal(keys[i-1], make([]byte, 24)))
	}

	// Output:
	// Key #1: true
	// Key #2: true
	// Key #3: true
}
开发者ID:Rudloff,项目名称:platform,代码行数:46,代码来源:example_test.go


示例20: deriveSymmetricKeys

// deriveSymmetricKeys derives the symmetric cryptoKey and hmacKey from the
// given messageKey.
func deriveSymmetricKeys(messageKey *[64]byte) (
	cryptoKey, hmacKey []byte,
	err error,
) {
	hkdf := hkdf.New(sha512.New, messageKey[:], nil, nil)

	// derive crypto key for AES-256
	cryptoKey = make([]byte, 32)
	if _, err := io.ReadFull(hkdf, cryptoKey); err != nil {
		return nil, nil, err
	}

	// derive HMAC key for SHA-512 HMAC
	hmacKey = make([]byte, 32)
	if _, err := io.ReadFull(hkdf, hmacKey); err != nil {
		return nil, nil, err
	}

	return
}
开发者ID:JonathanLogan,项目名称:mute,代码行数:22,代码来源:keys.go



注:本文中的golang.org/x/crypto/hkdf.New函数示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Golang box.GenerateKey函数代码示例发布时间:2022-05-28
下一篇:
Golang curve25519.ScalarMult函数代码示例发布时间:2022-05-28
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap