Skip to content
Snippets Groups Projects
generate_certificate.go 5.52 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
    Copyright (c) 2018 Vereign AG [https://www.vereign.com]
    
    This is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.
    
    You should have received a copy of the GNU Affero General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
    */
    
    package handler
    
    
    /* TODO remove this file
    
    func (s *KeyStorageServerImpl) GenerateCertificate(ctx context.Context, in *api.GenerateCertificateRequest) (*api.GenerateCertificateResponse, error) {
    	auth := s.CreateAuthentication(ctx)
    
    	client := &client.DataStorageClientImpl{}
    	client.SetUpClient(auth, s.DataStorageUrl, s.CertFilePath)
    	defer client.CloseClient()
    
    	generateCertificateResponse := &api.GenerateCertificateResponse{}
    
    
    	publicKeyMessage, statusList := getKey(client, in.Uuid, api.KeyType_PUBLIC)
    	if statusList != nil {
    		generateCertificateResponse.StatusList = statusList
    
    	certificateBytes, err := generateCertificate(publicKeyMessage.Content, s.VereignCertFilePath,
    		s.VereignPrivateKeyFilePath, in.CertificateData)
    
    	if err != nil {
    		generateCertificateResponse.StatusList = utils.AddStatus(generateCertificateResponse.StatusList,
    			"400", api.StatusType_ERROR, err.Error())
    		return generateCertificateResponse, nil
    	}
    
    	certificateMessage := &api.Key{
    		Content: certificateBytes,
    	}
    
    
    Olgun Cengiz's avatar
    Olgun Cengiz committed
    	result, errors, err := client.PutData("keys", in.Uuid+"/"+api.KeyType.String(api.KeyType_CERTIFICATE), certificateMessage)
    
    	generateCertificateResponse.StatusList = handlePutDataErrors(generateCertificateResponse.StatusList, errors, err)
    
    	if generateCertificateResponse.StatusList == nil || len(generateCertificateResponse.StatusList) == 0 {
    		generateCertificateResponse.StatusList = utils.AddStatus(generateCertificateResponse.StatusList,
    			"200", api.StatusType_INFO, result)
    	}
    
    	return generateCertificateResponse, nil
    }
    
    
    func generateCertificate(publicKeyBytes []byte, caCertFilePath string, caPrivateKeyFilePath string,
    
    	certificateData *api.CertificateData) ([]byte, error) {
    
    	publicKeyPemBlock, _ := pem.Decode(publicKeyBytes)
    
    	publicKey, err := x509.ParsePKIXPublicKey(publicKeyPemBlock.Bytes)
    
    	notBeforeTime := time.Unix(certificateData.NotBefore/1000, 0).UTC()
    	notAfterTime := time.Unix(certificateData.NotAfter/1000, 0).UTC()
    
    	max := new(big.Int)
    	max.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(max, big.NewInt(1))
    
    	//Generate cryptographically strong pseudo-random between 0 - max
    	sn, err := rand.Int(rand.Reader, max)
    
    	if err != nil {
    		return nil, err
    	}
    
    		SerialNumber: sn,
    
    		Subject: pkix.Name{
    			CommonName:         certificateData.CommonName,
    		},
    
    		NotBefore:             	notBeforeTime,
    		NotAfter:              	notAfterTime,
    		KeyUsage:              	x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment | x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    		ExtKeyUsage:           	[]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageEmailProtection, x509.ExtKeyUsageTimeStamping},
    
    		BasicConstraintsValid: 	true,
    		IsCA:     				true,
    	}
    
    	if certificateData.Country != "" {
    		template.Subject.Country = []string{certificateData.Country}
    	}
    	if certificateData.Locality != "" {
    		template.Subject.Locality = []string{certificateData.Locality}
    	}
    	if certificateData.Province != "" {
    		template.Subject.Province = []string{certificateData.Province}
    	}
    	if certificateData.Organization != "" {
    		template.Subject.Organization = []string{certificateData.Organization}
    	}
    	if certificateData.OrganizationalUnit != "" {
    		template.Subject.OrganizationalUnit = []string{certificateData.OrganizationalUnit}
    	}
    	if certificateData.Host != "" {
    		template.DNSNames = []string{certificateData.Host}
    	}
    	if certificateData.Email != "" {
    		template.EmailAddresses = []string{certificateData.Email}
    
    		oidPKCS9EmailAddress := asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}
    		template.Subject.ExtraNames = []pkix.AttributeTypeAndValue{
    			{
    				Type:  oidPKCS9EmailAddress,
    				Value: certificateData.Email,
    			},
    		}
    
    	}
    
    	caCertificate, err := readCertificateFromFile(caCertFilePath)
    	if err != nil {
    		return nil, err
    	}
    
    	caPrivateKey, err := readPrivateKeyFromFile(caPrivateKeyFilePath)
    	if err != nil {
    		return nil, err
    	}
    
    	certificateBytes, err := x509.CreateCertificate(rand.Reader, &template, caCertificate, publicKey, caPrivateKey)
    
    	certificatePemBlock := &pem.Block{
    		Type:  "CERTIFICATE",
    		Bytes: certificateBytes,
    	}
    
    	certificatePemBytes := pem.EncodeToMemory(certificatePemBlock)
    
    	return certificatePemBytes, nil
    
    }
    
    func readPrivateKeyFromFile(fileName string) (*rsa.PrivateKey, error) {
    	privateKeyPemBlock, err := readPemBlockFromFile(fileName)
    	if err != nil {
    		return nil, err
    	}
    
    	parseResult, err := x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes)
    	if err != nil {
    		return nil, err
    	}
    	privateKey := parseResult.(*rsa.PrivateKey)
    
    	return privateKey, nil
    }
    
    func readPemBlockFromFile(fileName string) (*pem.Block, error) {
    	fileBytes, err := ioutil.ReadFile(fileName)
    	if err != nil {
    		return nil, err
    	}
    
    	certificatePemBlock, _ := pem.Decode(fileBytes)
    
    	return certificatePemBlock, nil
    }